Subscription management and bandwidth accounting
This commit is contained in:
@@ -23,7 +23,7 @@
|
|||||||
<a href="/api">API</a>
|
<a href="/api">API</a>
|
||||||
<a href="/acknowledgements">Acknowledgements</a>
|
<a href="/acknowledgements">Acknowledgements</a>
|
||||||
<a href="https://stats.uptimerobot.com/p9v2ktzyjm" target="_blank">Server Status</a>
|
<a href="https://stats.uptimerobot.com/p9v2ktzyjm" target="_blank">Server Status</a>
|
||||||
{{if eq .User.Subscription.DisableAdDisplay false}}
|
{{if eq .User.Subscription.ID ""}}
|
||||||
<a href="https://pixeldrain.com/vouchercodes">Shopping discounts</a>
|
<a href="https://pixeldrain.com/vouchercodes">Shopping discounts</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -5,14 +5,14 @@ import Chart from "../util/Chart.svelte";
|
|||||||
|
|
||||||
let graphViews
|
let graphViews
|
||||||
let graphBandwidth
|
let graphBandwidth
|
||||||
let graphHotlink
|
let graphBandwidthPaid
|
||||||
let graphTimeout = null
|
let graphTimeout = null
|
||||||
|
|
||||||
let start_time = ""
|
let start_time = ""
|
||||||
let end_time = ""
|
let end_time = ""
|
||||||
let total_bandwidth = 0
|
let total_bandwidth = 0
|
||||||
let total_views = 0
|
let total_views = 0
|
||||||
let total_hotlink = 0
|
let total_bandwidth_paid = 0
|
||||||
const loadGraph = (minutes, interval, live) => {
|
const loadGraph = (minutes, interval, live) => {
|
||||||
if (graphTimeout !== null) { clearTimeout(graphTimeout) }
|
if (graphTimeout !== null) { clearTimeout(graphTimeout) }
|
||||||
if (live) {
|
if (live) {
|
||||||
@@ -44,17 +44,17 @@ const loadGraph = (minutes, interval, live) => {
|
|||||||
graphViews.chart().data.datasets[0].data = resp.views.amounts;
|
graphViews.chart().data.datasets[0].data = resp.views.amounts;
|
||||||
graphBandwidth.chart().data.labels = resp.views.timestamps;
|
graphBandwidth.chart().data.labels = resp.views.timestamps;
|
||||||
graphBandwidth.chart().data.datasets[0].data = resp.bandwidth.amounts;
|
graphBandwidth.chart().data.datasets[0].data = resp.bandwidth.amounts;
|
||||||
graphHotlink.chart().data.labels = resp.views.timestamps;
|
graphBandwidthPaid.chart().data.labels = resp.views.timestamps;
|
||||||
graphHotlink.chart().data.datasets[0].data = resp.direct_link_bandwidth.amounts;
|
graphBandwidthPaid.chart().data.datasets[0].data = resp.bandwidth_paid.amounts;
|
||||||
graphViews.update()
|
graphViews.update()
|
||||||
graphBandwidth.update()
|
graphBandwidth.update()
|
||||||
graphHotlink.update()
|
graphBandwidthPaid.update()
|
||||||
|
|
||||||
start_time = resp.views.timestamps[0]
|
start_time = resp.views.timestamps[0]
|
||||||
end_time = resp.views.timestamps.slice(-1)[0];
|
end_time = resp.views.timestamps.slice(-1)[0];
|
||||||
total_bandwidth = resp.bandwidth.amounts.reduce((acc, val) => acc + val)
|
total_bandwidth = resp.bandwidth.amounts.reduce((acc, val) => acc + val)
|
||||||
total_views = resp.views.amounts.reduce((acc, val) => acc + val)
|
total_views = resp.views.amounts.reduce((acc, val) => acc + val)
|
||||||
total_hotlink = resp.direct_link_bandwidth.amounts.reduce((acc, val) => acc + val)
|
total_bandwidth_paid = resp.bandwidth_paid.amounts.reduce((acc, val) => acc + val)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,13 +141,13 @@ onDestroy(() => {
|
|||||||
</div>
|
</div>
|
||||||
<Chart bind:this={graphBandwidth} dataType="bytes" label="Bandwidth" />
|
<Chart bind:this={graphBandwidth} dataType="bytes" label="Bandwidth" />
|
||||||
<hr/>
|
<hr/>
|
||||||
<Chart bind:this={graphHotlink} dataType="bytes" label="Hotlink bandwidth" />
|
<Chart bind:this={graphBandwidthPaid} dataType="bytes" label="Paid bandwidth" />
|
||||||
<hr/>
|
<hr/>
|
||||||
<Chart bind:this={graphViews} dataType="number" label="Views" />
|
<Chart bind:this={graphViews} dataType="number" label="Views" />
|
||||||
<div class="highlight_dark">
|
<div class="highlight_dark">
|
||||||
Total usage from {start_time} to {end_time}<br/>
|
Total usage from {start_time} to {end_time}<br/>
|
||||||
{formatDataVolume(total_bandwidth, 3)} bandwidth,
|
{formatDataVolume(total_bandwidth, 3)} bandwidth,
|
||||||
{formatDataVolume(total_hotlink, 3)} hotlink bandwidth and
|
{formatDataVolume(total_bandwidth_paid, 3)} paid bandwidth and
|
||||||
{formatThousands(total_views, 3)} views
|
{formatThousands(total_views, 3)} views
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -45,6 +45,9 @@ let update_charts = () => {
|
|||||||
resp.bandwidth.amounts.forEach((val, idx) => {
|
resp.bandwidth.amounts.forEach((val, idx) => {
|
||||||
resp.bandwidth.amounts[idx] = Math.round(val / file.size);
|
resp.bandwidth.amounts[idx] = Math.round(val / file.size);
|
||||||
});
|
});
|
||||||
|
resp.bandwidth_paid.amounts.forEach((val, idx) => {
|
||||||
|
resp.bandwidth.amounts[idx] += Math.round(val / file.size);
|
||||||
|
});
|
||||||
download_chart.chart().data.labels = resp.views.timestamps
|
download_chart.chart().data.labels = resp.views.timestamps
|
||||||
view_chart.chart().data.labels = resp.views.timestamps
|
view_chart.chart().data.labels = resp.views.timestamps
|
||||||
download_chart.chart().data.datasets[0].data = resp.bandwidth.amounts
|
download_chart.chart().data.datasets[0].data = resp.bandwidth.amounts
|
||||||
@@ -78,8 +81,20 @@ let update_charts = () => {
|
|||||||
<td>{formatDataVolume(file.size, 4)} ( {formatThousands(file.size)} B )</td>
|
<td>{formatDataVolume(file.size, 4)} ( {formatThousands(file.size)} B )</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Bandwidth</td>
|
<td>Free bandwidth used</td>
|
||||||
<td>{formatDataVolume(file.bandwidth_used, 4)} ( {formatThousands(file.bandwidth_used)} B )</td>
|
<td>
|
||||||
|
{formatDataVolume(file.bandwidth_used, 4)}
|
||||||
|
( {formatThousands(file.bandwidth_used)} B ),
|
||||||
|
{(file.bandwidth_used/file.size).toFixed(1)}x file size
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Premium bandwidth used</td>
|
||||||
|
<td>
|
||||||
|
{formatDataVolume(file.bandwidth_used_paid, 4)}
|
||||||
|
( {formatThousands(file.bandwidth_used_paid)} B ),
|
||||||
|
{(file.bandwidth_used_paid/file.size).toFixed(1)}x file size
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr style="border-bottom: none">
|
<tr style="border-bottom: none">
|
||||||
<td>Unique downloads</td>
|
<td>Unique downloads</td>
|
||||||
|
@@ -50,7 +50,7 @@ let update_stats = (id) => {
|
|||||||
if (file.size === 0) {
|
if (file.size === 0) {
|
||||||
downloads = j.downloads
|
downloads = j.downloads
|
||||||
} else {
|
} else {
|
||||||
downloads = Math.round(j.bandwidth / file.size)
|
downloads = Math.round((j.bandwidth + j.bandwidth_paid) / file.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
socket.onerror = err => {
|
socket.onerror = err => {
|
||||||
|
@@ -437,7 +437,7 @@ const keyboard_event = evt => {
|
|||||||
</FilePreview>
|
</FilePreview>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if current_file.show_ads && window.viewer_data.user_ads_enabled}
|
{#if current_file.show_ads}
|
||||||
<AdSkyscraper on:visibility={e => {skyscraper_visible = e.detail}}></AdSkyscraper>
|
<AdSkyscraper on:visibility={e => {skyscraper_visible = e.detail}}></AdSkyscraper>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
@@ -9,13 +9,13 @@ import Euro from "../util/Euro.svelte"
|
|||||||
let graph_view = null
|
let graph_view = null
|
||||||
let graph_download = null
|
let graph_download = null
|
||||||
let graph_bandwidth = null
|
let graph_bandwidth = null
|
||||||
let graph_direct_link = null
|
let graph_transfer_paid = null
|
||||||
let time_start = ""
|
let time_start = ""
|
||||||
let time_end = ""
|
let time_end = ""
|
||||||
let total_views = 0
|
let total_views = 0
|
||||||
let total_downloads = 0
|
let total_downloads = 0
|
||||||
let total_bandwidth = 0
|
let total_bandwidth = 0
|
||||||
let total_direct_link = 0
|
let total_transfer_paid = 0
|
||||||
|
|
||||||
let load_graph = (graph, stat, minutes, interval) => {
|
let load_graph = (graph, stat, minutes, interval) => {
|
||||||
let today = new Date()
|
let today = new Date()
|
||||||
@@ -54,8 +54,8 @@ let load_graph = (graph, stat, minutes, interval) => {
|
|||||||
total_downloads = total;
|
total_downloads = total;
|
||||||
} else if (stat == "bandwidth") {
|
} else if (stat == "bandwidth") {
|
||||||
total_bandwidth = total;
|
total_bandwidth = total;
|
||||||
} else if (stat == "direct_bandwidth") {
|
} else if (stat == "transfer_paid") {
|
||||||
total_direct_link = total;
|
total_transfer_paid = total;
|
||||||
}
|
}
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.error("Error requesting time series: " + e);
|
console.error("Error requesting time series: " + e);
|
||||||
@@ -75,11 +75,12 @@ let update_graphs = (minutes, interval, live) => {
|
|||||||
load_graph(graph_view, "views", minutes, interval)
|
load_graph(graph_view, "views", minutes, interval)
|
||||||
load_graph(graph_download, "downloads", minutes, interval)
|
load_graph(graph_download, "downloads", minutes, interval)
|
||||||
load_graph(graph_bandwidth, "bandwidth", minutes, interval)
|
load_graph(graph_bandwidth, "bandwidth", minutes, interval)
|
||||||
load_graph(graph_direct_link, "direct_bandwidth", minutes, interval)
|
load_graph(graph_transfer_paid, "transfer_paid", minutes, interval)
|
||||||
load_direct_bw()
|
load_direct_bw()
|
||||||
}
|
}
|
||||||
|
|
||||||
let direct_link_bandwidth_used = 0
|
let transfer_cap = 0
|
||||||
|
let transfer_used = 0
|
||||||
let storage_space_used = 0
|
let storage_space_used = 0
|
||||||
let load_direct_bw = () => {
|
let load_direct_bw = () => {
|
||||||
let today = new Date()
|
let today = new Date()
|
||||||
@@ -87,7 +88,7 @@ let load_direct_bw = () => {
|
|||||||
start.setDate(start.getDate() - 30)
|
start.setDate(start.getDate() - 30)
|
||||||
|
|
||||||
fetch(
|
fetch(
|
||||||
window.api_endpoint + "/user/time_series/direct_bandwidth" +
|
window.api_endpoint + "/user/time_series/transfer_paid" +
|
||||||
"?start=" + start.toISOString() +
|
"?start=" + start.toISOString() +
|
||||||
"&end=" + today.toISOString() +
|
"&end=" + today.toISOString() +
|
||||||
"&interval=60"
|
"&interval=60"
|
||||||
@@ -96,7 +97,7 @@ let load_direct_bw = () => {
|
|||||||
return resp.json();
|
return resp.json();
|
||||||
}).then(resp => {
|
}).then(resp => {
|
||||||
let total = resp.amounts.reduce((accum, val) => accum += val, 0);
|
let total = resp.amounts.reduce((accum, val) => accum += val, 0);
|
||||||
direct_link_bandwidth_used = total
|
transfer_used = total
|
||||||
storage_space_used = window.user.storage_space_used
|
storage_space_used = window.user.storage_space_used
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.error("Error requesting time series: " + e);
|
console.error("Error requesting time series: " + e);
|
||||||
@@ -104,6 +105,14 @@ let load_direct_bw = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
if (window.user.subscription.monthly_transfer_cap > 0) {
|
||||||
|
transfer_cap = window.user.subscription.monthly_transfer_cap
|
||||||
|
} else if (window.user.monthly_transfer_cap > 0) {
|
||||||
|
transfer_cap = window.user.monthly_transfer_cap
|
||||||
|
} else {
|
||||||
|
transfer_cap = -1
|
||||||
|
}
|
||||||
|
|
||||||
update_graphs(1440, 1, true);
|
update_graphs(1440, 1, true);
|
||||||
})
|
})
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
@@ -128,14 +137,6 @@ onDestroy(() => {
|
|||||||
<li>
|
<li>
|
||||||
Max file size: {formatDataVolume(window.user.subscription.file_size_limit, 3)}
|
Max file size: {formatDataVolume(window.user.subscription.file_size_limit, 3)}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
Advertisements when you view files:
|
|
||||||
{#if window.user.subscription.disable_ad_display}No{:else}Yes{/if}
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Advertisements when others view your files:
|
|
||||||
{#if window.user.subscription.disable_ads_on_files}No{:else}Yes{/if}
|
|
||||||
</li>
|
|
||||||
{#if window.user.subscription.file_expiry_days > 0}
|
{#if window.user.subscription.file_expiry_days > 0}
|
||||||
<li>Files expire after {window.user.subscription.file_expiry_days} days</li>
|
<li>Files expire after {window.user.subscription.file_expiry_days} days</li>
|
||||||
{:else}
|
{:else}
|
||||||
@@ -156,10 +157,10 @@ onDestroy(() => {
|
|||||||
<StorageProgressBar used={storage_space_used} total={window.user.subscription.storage_space}></StorageProgressBar>
|
<StorageProgressBar used={storage_space_used} total={window.user.subscription.storage_space}></StorageProgressBar>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if window.user.subscription.direct_linking_bandwidth === -1}
|
{#if transfer_cap === -1}
|
||||||
Hotlink bandwidth used in the last 30 days: {formatDataVolume(direct_link_bandwidth_used, 3)}<br/>
|
Paid transfers in the last 30 days: {formatDataVolume(transfer_used, 3)}<br/>
|
||||||
{:else}
|
{:else}
|
||||||
<HotlinkProgressBar used={direct_link_bandwidth_used} total={window.user.subscription.direct_linking_bandwidth}></HotlinkProgressBar>
|
<HotlinkProgressBar used={transfer_used} total={transfer_cap}></HotlinkProgressBar>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<h3>Exports</h3>
|
<h3>Exports</h3>
|
||||||
@@ -224,8 +225,18 @@ onDestroy(() => {
|
|||||||
{formatThousands(total_views)} views,
|
{formatThousands(total_views)} views,
|
||||||
{formatThousands(total_downloads)} downloads,
|
{formatThousands(total_downloads)} downloads,
|
||||||
{formatDataVolume(total_bandwidth, 3)} bandwidth and
|
{formatDataVolume(total_bandwidth, 3)} bandwidth and
|
||||||
{formatDataVolume(total_direct_link, 3)} direct link bandwidth
|
{formatDataVolume(total_transfer_paid, 3)} paid transfers
|
||||||
</div>
|
</div>
|
||||||
|
<div class="limit_width">
|
||||||
|
<h3>Paid transfers</h3>
|
||||||
|
<p>
|
||||||
|
A paid transfer is when a file is downloaded using the data cap on
|
||||||
|
your subscription plan. These can be files you downloaded from other
|
||||||
|
people, or other people downloading your files if you have bandwidth
|
||||||
|
sharing enabled.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<Chart bind:this={graph_transfer_paid} dataType="bytes" label="Paid transfers" />
|
||||||
<div class="limit_width">
|
<div class="limit_width">
|
||||||
<h3>Views</h3>
|
<h3>Views</h3>
|
||||||
<p>
|
<p>
|
||||||
@@ -255,17 +266,4 @@ onDestroy(() => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Chart bind:this={graph_bandwidth} dataType="bytes" label="Bandwidth" />
|
<Chart bind:this={graph_bandwidth} dataType="bytes" label="Bandwidth" />
|
||||||
<div class="limit_width">
|
|
||||||
<h3>Hotlink bandwidth</h3>
|
|
||||||
<p>
|
|
||||||
When a file is downloaded without going through pixeldrain's
|
|
||||||
download page it counts as a hotlink. Because hotlinking costs us
|
|
||||||
bandwidth and doesn't generate any ad revenue we have to limit it.
|
|
||||||
When your hotlink bandwidth runs out people will be asked to do a
|
|
||||||
test before they can download your files. See our
|
|
||||||
<a href="/#pro">subscription options</a> to get more hotlink
|
|
||||||
bandwidth.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<Chart bind:this={graph_direct_link} dataType="bytes" label="Hotlink bandwidth" />
|
|
||||||
</div>
|
</div>
|
||||||
|
@@ -8,7 +8,7 @@ $: frac = used / total
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
Hotlink bandwidth:
|
Paid transfers:
|
||||||
{formatDataVolume(used, 3)}
|
{formatDataVolume(used, 3)}
|
||||||
out of
|
out of
|
||||||
{formatDataVolume(total, 3)}
|
{formatDataVolume(total, 3)}
|
||||||
@@ -20,10 +20,9 @@ $: frac = used / total
|
|||||||
|
|
||||||
{#if frac > 0.99}
|
{#if frac > 0.99}
|
||||||
<div class="highlight_red">
|
<div class="highlight_red">
|
||||||
You have used all of your hotlink bandwidth. Other people won't
|
You have used all of your data cap. People can still download your
|
||||||
be able to download your files directly from the API anymore.
|
files, but not directly from the API anymore. The file viewer shows
|
||||||
Downloads will have to go through the file viewer page. Please
|
ads on your files and download speeds are limited.
|
||||||
upgrade to a higher support tier to continue hotlinking files:
|
|
||||||
<br/>
|
<br/>
|
||||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||||
Upgrade options
|
Upgrade options
|
||||||
@@ -31,12 +30,10 @@ $: frac = used / total
|
|||||||
</div>
|
</div>
|
||||||
{:else if frac > 0.8}
|
{:else if frac > 0.8}
|
||||||
<div class="highlight_yellow">
|
<div class="highlight_yellow">
|
||||||
You have used {(frac*100).toFixed(0)}% of your
|
You have used {(frac*100).toFixed(0)}% of your data cap. If your
|
||||||
hotlink bandwidth. If your hotlink bandwidth runs out people
|
data runs out people won't be able to download your files directly
|
||||||
won't be able to download your files directly from the API
|
from the API anymore, ads will be shown on the file viewer and
|
||||||
anymore. Downloads will have to go through the file viewer page.
|
transfer rates will be limited.
|
||||||
Please upgrade to a higher support tier to continue hotlinking
|
|
||||||
files:
|
|
||||||
<br/>
|
<br/>
|
||||||
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
|
||||||
Upgrade options
|
Upgrade options
|
||||||
|
@@ -55,6 +55,13 @@ onMount(() => {
|
|||||||
<i class="icon">vpn_key</i>
|
<i class="icon">vpn_key</i>
|
||||||
API keys
|
API keys
|
||||||
</a>
|
</a>
|
||||||
|
<a class="button"
|
||||||
|
href="/user/subscription"
|
||||||
|
class:button_highlight={page === "subscription"}
|
||||||
|
on:click|preventDefault={() => {navigate("subscription", "Subscription")}}>
|
||||||
|
<i class="icon">shopping_cart</i>
|
||||||
|
Subscription
|
||||||
|
</a>
|
||||||
{#if window.user.balance_micro_eur !== 0}
|
{#if window.user.balance_micro_eur !== 0}
|
||||||
<a class="button"
|
<a class="button"
|
||||||
href="/user/transactions"
|
href="/user/transactions"
|
||||||
@@ -63,13 +70,6 @@ onMount(() => {
|
|||||||
<i class="icon">receipt_long</i>
|
<i class="icon">receipt_long</i>
|
||||||
Transactions
|
Transactions
|
||||||
</a>
|
</a>
|
||||||
<a class="button"
|
|
||||||
href="/user/subscription"
|
|
||||||
class:button_highlight={page === "subscription"}
|
|
||||||
on:click|preventDefault={() => {navigate("subscription", "Subscription")}}>
|
|
||||||
<i class="icon">shopping_cart</i>
|
|
||||||
Subscription
|
|
||||||
</a>
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@@ -3,15 +3,20 @@ import Spinner from "../util/Spinner.svelte";
|
|||||||
import Euro from "../util/Euro.svelte"
|
import Euro from "../util/Euro.svelte"
|
||||||
|
|
||||||
let loading = false
|
let loading = false
|
||||||
|
let subscription = window.user.subscription.id
|
||||||
|
let hotlinking = window.user.hotlinking_enabled
|
||||||
|
let transfer_cap = window.user.monthly_transfer_cap / 1e12
|
||||||
|
|
||||||
let result = ""
|
let result = ""
|
||||||
let result_success = false
|
let result_success = false
|
||||||
|
|
||||||
const update_subscription = async name => {
|
const update_subscription = async () => {
|
||||||
loading = true
|
loading = true
|
||||||
|
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append("subscription", name)
|
form.append("subscription", subscription)
|
||||||
|
form.append("hotlinking_enabled", hotlinking)
|
||||||
|
form.append("transfer_cap", transfer_cap*1e12)
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(
|
const resp = await fetch(
|
||||||
window.api_endpoint+"/user/subscription",
|
window.api_endpoint+"/user/subscription",
|
||||||
@@ -62,97 +67,135 @@ const update_subscription = async name => {
|
|||||||
balance to activate the subscription again.
|
balance to activate the subscription again.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{#if result !== ""}
|
<h3>Prepaid plans</h3>
|
||||||
<div class:highlight_green={result_success} class:highlight_red={!result_success}>
|
{#if window.user.subscription.type === "patreon"}
|
||||||
{result}
|
<p>Prepaid subscriptions are not available for Patreon supporters.</p>
|
||||||
|
{:else}
|
||||||
|
{#if result !== ""}
|
||||||
|
<div class:highlight_green={result_success} class:highlight_red={!result_success}>
|
||||||
|
{result}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class="feat_table">
|
||||||
|
<div>
|
||||||
|
<div class="feat_label" class:feat_highlight={subscription === "prepaid"}>
|
||||||
|
Prepaid<br/>
|
||||||
|
{#if subscription === "prepaid"}
|
||||||
|
Currently active
|
||||||
|
{:else}
|
||||||
|
<button on:click={() => {subscription = "prepaid"; update_subscription()}}>
|
||||||
|
<i class="icon">attach_money</i>
|
||||||
|
Activate
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="feat_normal round_tr">
|
||||||
|
<ul>
|
||||||
|
<li>Base price of €1 per month</li>
|
||||||
|
<li>€4 per TB per month for storage</li>
|
||||||
|
<li>€2 per TB for data transfer</li>
|
||||||
|
<li>Files never expire as long as subscription is active</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="feat_label" class:feat_highlight={subscription === "prepaid_temp_storage_120d"}>
|
||||||
|
120 days storage<br/>
|
||||||
|
{#if subscription === "prepaid_temp_storage_120d"}
|
||||||
|
Currently active
|
||||||
|
{:else}
|
||||||
|
<button on:click={() => {subscription = "prepaid_temp_storage_120d"; update_subscription()}}>
|
||||||
|
<i class="icon">attach_money</i>
|
||||||
|
Activate
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="feat_normal">
|
||||||
|
<ul>
|
||||||
|
<li>Base price of €1 per month</li>
|
||||||
|
<li>€2 per TB per month for storage</li>
|
||||||
|
<li>€2 per TB for data transfer</li>
|
||||||
|
<li>Files expire 120 days after the last time they're viewed</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="feat_label" class:feat_highlight={subscription === "prepaid_temp_storage_60d"}>
|
||||||
|
60 days storage<br/>
|
||||||
|
{#if subscription === "prepaid_temp_storage_60d"}
|
||||||
|
Currently active
|
||||||
|
{:else}
|
||||||
|
<button on:click={() => {subscription = "prepaid_temp_storage_60d"; update_subscription()}}>
|
||||||
|
<i class="icon">attach_money</i>
|
||||||
|
Activate
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="feat_normal">
|
||||||
|
<ul>
|
||||||
|
<li>Base price of €1 per month</li>
|
||||||
|
<li>€1 per TB per month for storage</li>
|
||||||
|
<li>€2 per TB for data transfer</li>
|
||||||
|
<li>Files expire 60 days after the last time they're viewed</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="feat_label" class:feat_highlight={subscription === ""}>
|
||||||
|
Free<br/>
|
||||||
|
{#if subscription === ""}
|
||||||
|
Currently active
|
||||||
|
{:else}
|
||||||
|
<button on:click={() => {subscription = ""; update_subscription()}}>
|
||||||
|
<i class="icon">money_off</i>
|
||||||
|
Activate
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="feat_normal round_br">
|
||||||
|
<ul>
|
||||||
|
<li>Standard free plan, files expire after 30 days.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="feat_table">
|
<h3>Bandwidth sharing</h3>
|
||||||
<div>
|
|
||||||
<div class="feat_label" class:feat_highlight={window.user.subscription.id === "prepaid"}>
|
{#if hotlinking}
|
||||||
Prepaid<br/>
|
<button on:click={() => { hotlinking = false; update_subscription() }}>
|
||||||
{#if window.user.subscription.id === "prepaid"}
|
<i class="icon green">check</i> ON (click to turn off)
|
||||||
Currently active
|
</button>
|
||||||
{:else}
|
{:else}
|
||||||
<button on:click={() => {update_subscription("prepaid")}}>
|
<button on:click={() => { hotlinking = true; update_subscription() }}>
|
||||||
<i class="icon">attach_money</i>
|
<i class="icon red">close</i> OFF (click to turn on)
|
||||||
Activate
|
</button>
|
||||||
</button>
|
{/if}
|
||||||
{/if}
|
<p>
|
||||||
</div>
|
When bandwidth sharing is enabled all the bandwidth that your files
|
||||||
<div class="feat_normal round_tr">
|
use will be subtracted from your data cap. Advertisements will be
|
||||||
<ul>
|
disabled on the download pages for your files and download speed
|
||||||
<li>Base price of €2 per month (includes all the benefits of the Pro plan)</li>
|
will be unlimited. The rate limiting captcha for files is also
|
||||||
<li>€4 per TB per month for storage</li>
|
disabled when bandwidth sharing is on. You can directly embed your
|
||||||
<li>€2 per TB for hotlink bandwidth</li>
|
file's download link anywhere, you don't need to use the file viewer
|
||||||
<li>All advertisements disabled</li>
|
page.
|
||||||
<li>No rate limit, your files will download at the highest speed possible</li>
|
</p>
|
||||||
</ul>
|
|
||||||
</div>
|
<h3>Bill shock limit</h3>
|
||||||
</div>
|
Billshock limit in terabytes per month. Set to 0 to disable<br/>
|
||||||
<div>
|
<input type="number" bind:value={transfer_cap}/> TB
|
||||||
<div class="feat_label" class:feat_highlight={window.user.subscription.id === "prepaid_storage"}>
|
<button on:click={update_subscription}>
|
||||||
Just storage<br/>
|
<i class="icon">save</i> Save
|
||||||
{#if window.user.subscription.id === "prepaid_storage"}
|
</button>
|
||||||
Currently active
|
<p>
|
||||||
{:else}
|
The billshock limit limits how much bandwidth your account can use
|
||||||
<button on:click={() => {update_subscription("prepaid_storage")}}>
|
in a 30 day window. When this limit is reached files will show ads
|
||||||
<i class="icon">attach_money</i>
|
again and can only be downloaded from the file viewer page. This is
|
||||||
Activate
|
mostly useful for prepaid plans, but it works for patreon plans too.
|
||||||
</button>
|
Set to 0 to disable the limit.
|
||||||
{/if}
|
</p>
|
||||||
</div>
|
|
||||||
<div class="feat_normal">
|
|
||||||
<ul>
|
|
||||||
<li>Base price of €1 per month</li>
|
|
||||||
<li>€4 per TB per month for storage</li>
|
|
||||||
<li>100 GB of hotlink bandwidth per month</li>
|
|
||||||
<li>You don't see ads, but people downloading your files do see ads</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="feat_label" class:feat_highlight={window.user.subscription.id === "prepaid_storage_temp"}>
|
|
||||||
Temporary storage<br/>
|
|
||||||
{#if window.user.subscription.id === "prepaid_storage_temp"}
|
|
||||||
Currently active
|
|
||||||
{:else}
|
|
||||||
<button on:click={() => {update_subscription("prepaid_storage_temp")}}>
|
|
||||||
<i class="icon">attach_money</i>
|
|
||||||
Activate
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<div class="feat_normal">
|
|
||||||
<ul>
|
|
||||||
<li>Base price of €1 per month</li>
|
|
||||||
<li>€2 per TB per month for storage</li>
|
|
||||||
<li>100 GB of hotlink bandwidth per month</li>
|
|
||||||
<li>You don't see ads, but people downloading your files do see ads</li>
|
|
||||||
<li>Files expire 90 days after the last time they're viewed</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="feat_label" class:feat_highlight={window.user.subscription.id === ""}>
|
|
||||||
Free<br/>
|
|
||||||
{#if window.user.subscription.id === ""}
|
|
||||||
Currently active
|
|
||||||
{:else}
|
|
||||||
<button on:click={() => {update_subscription("none")}}>
|
|
||||||
<i class="icon">money_off</i>
|
|
||||||
Activate
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<div class="feat_normal round_br">
|
|
||||||
<ul>
|
|
||||||
<li>Standard free plan, files expire after 30 days.</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -204,4 +247,11 @@ const update_subscription = async name => {
|
|||||||
.feat_table > div > div.round_tr { border-top-right-radius: 0.5em; }
|
.feat_table > div > div.round_tr { border-top-right-radius: 0.5em; }
|
||||||
.feat_table > div > div.round_br { border-bottom-right-radius: 0.5em; }
|
.feat_table > div > div.round_br { border-bottom-right-radius: 0.5em; }
|
||||||
|
|
||||||
|
.green {
|
||||||
|
color: var(--highlight_color);
|
||||||
|
}
|
||||||
|
.red {
|
||||||
|
color: var(--danger_color);
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
@@ -74,7 +74,7 @@ func (wc *WebController) serveFileViewer(w http.ResponseWriter, r *http.Request,
|
|||||||
var vd = fileViewerData{
|
var vd = fileViewerData{
|
||||||
CaptchaKey: wc.captchaKey(),
|
CaptchaKey: wc.captchaKey(),
|
||||||
ViewToken: wc.viewTokenOrBust(),
|
ViewToken: wc.viewTokenOrBust(),
|
||||||
UserAdsEnabled: !(templateData.Authenticated && templateData.User.Subscription.DisableAdDisplay),
|
UserAdsEnabled: templateData.User.Subscription.ID == "",
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ids) > 1 {
|
if len(ids) > 1 {
|
||||||
@@ -149,7 +149,7 @@ func (wc *WebController) serveListViewer(w http.ResponseWriter, r *http.Request,
|
|||||||
Type: "list",
|
Type: "list",
|
||||||
CaptchaKey: wc.captchaSiteKey,
|
CaptchaKey: wc.captchaSiteKey,
|
||||||
ViewToken: wc.viewTokenOrBust(),
|
ViewToken: wc.viewTokenOrBust(),
|
||||||
UserAdsEnabled: !(templateData.Authenticated && templateData.User.Subscription.DisableAdDisplay),
|
UserAdsEnabled: templateData.User.Subscription.ID == "",
|
||||||
APIResponse: list,
|
APIResponse: list,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user