Finish patreon integration

This commit is contained in:
2021-01-11 21:43:04 +01:00
parent 7dae739e7b
commit 4e1f553207
10 changed files with 241 additions and 251 deletions

View File

@@ -6,6 +6,36 @@
✅ You are logged in to your pixeldrain account. Continue to the next step.
## Join a support tier in Patreon
<div style="text-align: center;">
{{$plan := .URLQuery.Get "plan"}}
{{if eq $plan "t5"}}
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5736701">
Order plan 'Resolve'
</a>
{{else if eq $plan "t2"}}
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291482">
Order plan 'Persistence'
</a>
{{else if eq $plan "t3"}}
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291516">
Order plan 'Tenacity'
</a>
{{else if eq $plan "t4"}}
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291528">
Order plan 'Eternity'
</a>
{{else}}
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427">
Order Pixeldrain Pro Plan
</a>
{{end}}
</div>
After ordering you will receive an e-mail on your Patreon e-mail address with a
link to activate your subscription.
{{else}}
❌ You are not logged into a pixeldrain account. If you do not have an account
@@ -13,56 +43,3 @@ yet you need to register one. You can do so with our [registration
form](/register). If you already have an account you can [log in here](/login).
{{end}}
## Verify your e-mail address
{{if eq .User.Email ""}}
❌ Your e-mail address is not yet verified. You can change your e-mail address on
the [user settings page](/user/settings). After submitting your e-mail address
you will receive a verification link in your inbox. Click the verification link
to verify your e-mail address.
{{else}}
✅ Your e-mail address is verified. Continue to the next step.
{{end}}
## Join a support tier in Patreon
Make sure your Patreon account uses the same e-mail address as your pixeldrain
account. {{if .Authenticated}}(Your e-mail address: {{.User.Email}}){{end}}
{{$plan := .URLQuery.Get "plan"}}
{{if eq $plan "t1"}}
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427">
Order plan 'I'm doing my part!'
</a>
{{else if eq $plan "t5"}}
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5736701">
Order plan 'Resolve'
</a>
{{else if eq $plan "t2"}}
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291482">
Order plan 'Persistence'
</a>
{{else if eq $plan "t3"}}
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291516">
Order plan 'Tenacity'
</a>
{{else if eq $plan "t4"}}
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291528">
Order plan 'Eternity'
</a>
{{else}}
<div style="text-align: center;">
<a class="button button_highlight" href="https://www.patreon.com/join/pixeldrain">
See our subscription plans on Patreon
</a>
</div>
{{end}}
After ordering you will receive an e-mail with a link to activate your
subscription. The subscription will be linked to the pixeldrain account you're
currently logged into.

View File

@@ -34,14 +34,14 @@ function UploadManager(uploadEndpoint, uploadsFinished) {
this.jobCounter = 0;
}
UploadManager.prototype.finishedUploads = function() {
UploadManager.prototype.finishedUploads = function () {
this.uploadLog.sort((a, b) => {
return a.jobID - b.jobID;
})
return this.uploadLog;
}
UploadManager.prototype.addFile = function(
UploadManager.prototype.addFile = function (
file, // Blob
name, // string
onProgress, // func (progress: number)
@@ -67,7 +67,7 @@ UploadManager.prototype.addFile = function(
}
}
UploadManager.prototype.startUpload = function() {
UploadManager.prototype.startUpload = function () {
if (this.uploadQueue.length === 0) {
return; // Nothing to upload
}
@@ -78,13 +78,13 @@ UploadManager.prototype.startUpload = function() {
}
}
UploadManager.prototype.finishUpload = function() {
UploadManager.prototype.finishUpload = function () {
this.activeWorkers--;
if (
this.uploadQueue.length === 0 &&
this.activeWorkers === 0 &&
typeof(this.uploadsFinished) === "function"
typeof (this.uploadsFinished) === "function"
) {
this.uploadsFinished();
return;
@@ -94,7 +94,7 @@ UploadManager.prototype.finishUpload = function() {
this.startUpload();
}
UploadManager.prototype.uploadThread = function() {
UploadManager.prototype.uploadThread = function () {
let job = this.uploadQueue.shift(); // Get the first element of the array
console.debug("Starting upload of " + job.name);
@@ -107,7 +107,7 @@ UploadManager.prototype.uploadThread = function() {
// Report progress updates back to the caller
xhr.upload.addEventListener("progress", evt => {
if (evt.lengthComputable && typeof(job.onProgress) === "function") {
if (evt.lengthComputable && typeof (job.onProgress) === "function") {
job.onProgress(evt.loaded / evt.total);
}
});
@@ -128,7 +128,7 @@ UploadManager.prototype.uploadThread = function() {
fileName: job.name
});
if (typeof(job.onFinished) === "function") {
if (typeof (job.onFinished) === "function") {
job.onFinished(resp.id);
}
@@ -138,7 +138,7 @@ UploadManager.prototype.uploadThread = function() {
// Request failed
console.log("Upload error. status: " + xhr.status + " response: " + xhr.response);
let resp = JSON.parse(xhr.response);
if (job.tries === 3) { // Upload failed
if (resp.value == "file_too_large" || job.tries === 3) { // Upload failed
job.onFailure(resp.value, resp.message);
} else { // Try again
job.tries++;
@@ -150,7 +150,7 @@ UploadManager.prototype.uploadThread = function() {
} else {
// Request did not arrive
if (job.tries === 3) { // Upload failed
if (typeof(job.onFailure) === "function") {
if (typeof (job.onFailure) === "function") {
job.onFailure(xhr.responseText, xhr.responseText);
}
} else { // Try again

View File

@@ -346,7 +346,7 @@ pre {
.file_button{
position: relative;
box-sizing: border-box;
width: 300px;
width: 400px;
max-width: 90%;
height: 3.6em;
margin: 10px;
@@ -432,6 +432,7 @@ select {
overflow: hidden;
font-size: 1em; /* Sometimes user-agents have different font sizes for buttons and links */
text-decoration: none;
text-shadow: none;
color: #bfbfbf; /* Fallback */
color: var(--input_text_color);
outline: 0;

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -18,22 +18,20 @@
<li>Username: {{.User.Username}}</li>
<li>E-mail address: {{.User.Email}}</li>
<li>
{{if eq .User.Subscription.Name ""}}
Supporter status: Not a pixeldrain supporter<br/>
<a href="https://www.patreon.com/pixeldrain">Learn how to support pixeldrain</a>.
{{else}}
Supporter level {{.User.Subscription.Name}}
<ul>
<li>Ads when viewing files: {{if .User.Subscription.DisableAdDisplay}}No{{else}}Yes{{end}}</li>
<li>Ads on your uploaded files: {{if .User.Subscription.DisableAdsOnFiles}}No{{else}}Yes{{end}}</li>
{{if gt .User.Subscription.FileExpiryDays 0}}
<li>Files expire after {{.User.Subscription.FileExpiryDays}} days</li>
{{else}}
<li>Files never expire</li>
{{end}}
<li>Direct linking bandwidth: {{formatData .User.Subscription.DirectLinkingBandwidth}}</li>
</ul>
Supporter level: {{.User.Subscription.Name}}
{{if ne .User.Subscription.ID ""}}
(<a href="https://www.patreon.com/join/pixeldrain/checkout?edit=1">Manage subscription</a>)
{{end}}
<ul>
<li>Ads when viewing files: {{if .User.Subscription.DisableAdDisplay}}No{{else}}Yes{{end}}</li>
<li>Ads on your uploaded files: {{if .User.Subscription.DisableAdsOnFiles}}No{{else}}Yes{{end}}</li>
{{if gt .User.Subscription.FileExpiryDays 0}}
<li>Files expire after {{.User.Subscription.FileExpiryDays}} days</li>
{{else}}
<li>Files never expire</li>
{{end}}
<li>File size limit: {{formatData .User.Subscription.FileSizeLimit}}</li>
</ul>
</li>
</ul>
<a href="/user/settings" class="button button_highlight">Change account settings</a>

View File

@@ -60,7 +60,7 @@
<label for="input_{{$field.Name}}_choice_{{$val}}">{{$val}}</label><br/>
{{ end }}
{{else if eq $field.Type "description"}}
<p>{{$field.DefaultValue}}</p>
{{$field.DefaultValue}}
{{end}}
</td>
{{end}}

View File

@@ -44,7 +44,7 @@
.instruction_text {
margin: 0.1em;
font-size: 1.5em;
display: inline-block;
display: inline;
box-sizing: border-box;
vertical-align: middle;
}
@@ -57,20 +57,31 @@
margin: 5px 15px;
}
.table_container {
width: 100%;
overflow-x: auto;
overflow-y: hidden;
}
.feat_table {
display: flex;
flex-direction: column;
min-width: 400px;
}
.feat_table > div {
display: flex;
flex-direction: row;
}
.feat_table > div > div:first-child { max-width: 14em; }
.feat_table > div > div:first-child {
flex: 0 0 20%;
max-width: 20%;
}
.feat_table > div > div {
flex: 1 0 0;
flex: 1 1 0;
margin: 0.2em;
padding: 0.5em;
text-align: center;
word-wrap: break-word;
hyphens: auto;
}
.feat_table > div > .feat_label {
border-top-left-radius: 0.5em;
@@ -97,23 +108,10 @@
font-weight: bold;
}
@media (max-width: 800px) {
.feat_table > div {
flex-direction: column;
margin: 0.2em;
border-radius: 6px;
}
.feat_table > div > div {
margin: 0;
border-radius: 0;
}
}
@media (min-width: 800px) {
.feat_table > div > div.round_tl { border-top-left-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_bl { border-bottom-left-radius: 0.5em; }
}
.feat_table > div > div.round_tl { border-top-left-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_bl { border-bottom-left-radius: 0.5em; }
{{template `modal.css`}}
</style>
@@ -126,7 +124,7 @@
<img class="header_image" src="/res/img/header_orbitron_wide.png" alt="Header image">
</picture>
<br/>
<div class="page_content" style="padding-top: 0;">
<div class="page_content" style="padding-top: 0; margin-bottom: 100px;">
<div id="instruction_1" class="instruction_highlight" style="margin-top: 0;"><div class="limit_width">
<span class="big_number">1</span>
<span class="instruction_text">Select files to upload</span>
@@ -185,7 +183,7 @@
{{template `tumblr.svg` .}}<br/>Tumblr
</button>
</div>
<br/>
<br/><br/>
<button id="btn_create_list"><i class="icon">list</i> Create list with uploaded files</button>
<button id="btn_copy_links"><i class="icon">content_copy</i> Copy all links to clipboard</button>
<button id="btn_copy_markdown"><i class="icon">content_copy</i> Copy markdown to clipboard</button>
@@ -193,44 +191,45 @@
<br/>
<div id="created_lists"></div>
</div>
</div>
<div class="limit_width">
<h2>What is pixeldrain?</h2>
<p>
Pixeldrain is a file sharing website built for speed and
ease of use. Pixeldrain does not cost any money, though
donations are appreciated. See how you can support
pixeldrain below.
</p>
<p>
Files can be uploaded by clicking the big green upload
button, or by dragging them onto this page from your file
manager. You can not upload directories at this time, only
files. The maximum file size you can upload is 10 GB.
</p>
<p>
You can also create lists, which are a collection of files.
Like a photo album, a music record or a video compilation.
To do this you need to upload a bunch of files at once. The
files will be saved in the order you uploaded them. When all
files have finished uploading you click the "Create list
with uploaded files" button and you will be asked to enter a
name for your list. After picking a name the list will be
created and opened in a new window. If your browser blocks
the window you can also find a link to the list at the
bottom of your uploaded files.
</p>
<p>
For more information about pixeldrain see the
<a href="/about">about</a> page.
</p>
<h1>What is pixeldrain?</h1>
<div class="page_content"><div class="limit_width">
<p>
Pixeldrain is a file sharing website built for speed and
ease of use. Pixeldrain does not cost any money, though
donations are appreciated. See how you can support
pixeldrain below.
</p>
<p>
Files can be uploaded by clicking the big green upload
button, or by dragging them onto this page from your file
manager.
</p>
<p>
You can also create lists, which are a collection of files.
Like a photo album, a music record or a video compilation.
To do this you need to upload a bunch of files at once. The
files will be saved in the order you uploaded them. When all
files have finished uploading you click the "Create list
with uploaded files" button and you will be asked to enter a
name for your list. After picking a name the list will be
created and opened in a new window. If your browser blocks
the window you can also find a link to the list at the
bottom of your uploaded files.
</p>
<p>
For more information about pixeldrain see the
<a href="/about">about</a> page.
</p>
<h2 id="pro">Pro</h2>
<p>
By purchasing a subscription you support pixeldrain on its
mission to make content sharing easier, safer and faster for
everyone.
</p>
<h2 id="pro">Getting more out of pixeldrain</h2>
<p>
By purchasing a subscription you support pixeldrain on its
mission to make content sharing easier, safer and faster for
everyone.
</p>
<div class="table_container">
<div class="feat_table">
<div>
<div></div>
@@ -248,12 +247,12 @@
<div class="feat_pro"><span class="text_highlight">90 days</span> after the last time it is viewed</div>
</div>
<div>
<div class="feat_label">Advertisements</div>
<div class="feat_label">Adver&shy;tise&shy;ments</div>
<div class="feat_normal">Pop-up or a banner ad on the file viewer page</div>
<div class="feat_pro">
<span class="text_highlight">No ads</span> on files
you share, or when viewing files from other
users
you share. No ads when viewing files uploaded by
other users
</div>
</div>
<div>
@@ -280,27 +279,36 @@
<div></div>
<div class="feat_normal round_bl">Free</div>
<div class="feat_pro feat_highlight round_br">
<button class="button_highlight">Only € 1 per month!</button>
{{if ne .User.Subscription.ID ""}}
You have this plan<br/>
Thank you for supporting pixeldrain!
{{else}}
<a href="https://www.patreon.com/join/pixeldrain/checkout?rid=5291427" class="button button_highlight">Only € 2 per month!</a> (Excluding tax)
<br/>
Billed annually. We accept Stripe and PayPal
Subscription managed by Patreon
{{end}}
</div>
</div>
</div>
<br/>
<h2>Premium</h2>
<p>
Premium is more catered toward file storage and content
delivery. This plan enables the Buckets feature which
provides a more structured way to manage your files on
pixeldrain. Buckets allow direct linking to files without
running into rate limiting.
</p>
<p>
When you choose for Premium you will also get all the
benefits of the Pro subscription.
</p>
</div>
</div>
<br/>
<h2>Premium</h2>
<div class="highlight_dark">
Pixeldrain Premium is still in development and not generally
available yet. Stay tuned.
</div>
<p>
Premium is more catered toward content delivery. This plan
enables the Buckets feature which provides a more structured way
to manage your files on pixeldrain. Buckets allow direct linking
to files without running into rate limiting.
</p>
<p>
When you choose for Premium you will also get all the benefits
of the Pro subscription. A base rate of €1 per month will be
billed regardless of your usage.
</p>
</div></div>
<template id="tpl_file_expiry">
<p>
@@ -314,7 +322,7 @@
gets 30 days by default (90 days if you have the pro plan).
After these 30 days we will check when the file was last viewed.
Files which are regularly viewed could still bring new users to
the platform, it would be rude to show these people a 404 Not
the platform, it would be rude to show these people a File Not
Found page. So if the file was viewed in the last 30 days we
will simply postpone the next check a month. If the file was not
viewed however it will immediately be removed.
@@ -332,22 +340,19 @@
<template id="tpl_direct_linking">
<p>
When viewing a file on pixeldrain it has to go through the file
viewer. Files which are directly downloaded without visiting the
file viewer are blocked after a while.
viewer. Files which have three times more downloads than views
will be rate limited. This happens when downloaders use external
downloading tools to download the file instead of a web browser.
</p>
<p>
Direct linking allows you to share files without going through
the file viewer. You can use this to embed videos / images in
your own webpages. Files which are direct linked won't count any
views but we will keep track of the downloads and used
bandwidth.
This means that the downloader will be asked to fill in a
captcha before they can download the file. When the file /
download ratio drops below 3x again the captcha will be removed
and direct downloads become possible again.
</p>
<p>
When you use up your direct linking bandwidth your direct links
will stop working for the rest of the month. You can always
upgrade to get more bandwidth. The amount of bandwidth used in
the month can be seen on your <a href="/user">user page</a> when
logged in.
If you need direct linking you can upgrade to the Premium plan.
Bandwidth will be billed per terabyte.
</p>
</template>

89
webcontroller/patreon.go Normal file
View File

@@ -0,0 +1,89 @@
package webcontroller
import (
"fmt"
"html/template"
"net/http"
)
func (wc *WebController) patreonLinkForm(td *TemplateData, r *http.Request) (f Form) {
f.Name = "link_patreon_subscription"
f.Title = "Link Patreon pledge to pixeldrain account"
f.SubmitLabel = "Submit"
if r.FormValue("key") == "" {
f.Submitted = true
f.SubmitMessages = []template.HTML{"Patron ID not found"}
return f
}
patron, err := td.PixelAPI.PatreonByID(r.FormValue("key"))
if err != nil && err.Error() == "not_found" {
f.Submitted = true
f.SubmitMessages = []template.HTML{"Patron ID not found"}
return f
} else if err != nil {
f.Submitted = true
formAPIError(err, &f)
return f
}
f.Fields = []Field{{
Name: "1",
Label: "",
DefaultValue: "",
Description: "<h3>Please confirm that the following information is correct:</h3>",
Type: FieldTypeDescription,
}, {
Name: "2",
Label: "Pixeldrain username",
DefaultValue: td.User.Username,
Type: FieldTypeDescription,
}, {
Name: "3",
Label: "Pixeldrain e-mail",
DefaultValue: td.User.Email,
Type: FieldTypeDescription,
}, {
Name: "4",
Label: "Patreon username",
DefaultValue: patron.FullName,
Type: FieldTypeDescription,
}, {
Name: "5",
Label: "Patreon e-mail",
DefaultValue: patron.UserEmail,
Type: FieldTypeDescription,
}, {
Name: "6",
Label: "Subscription name",
DefaultValue: patron.Subscription.Name,
Type: FieldTypeDescription,
}, {
Name: "7",
Label: "Monthly contribution",
DefaultValue: fmt.Sprintf("€ %.2f / month", float64(patron.PledgeAmountCents)/100.0),
Type: FieldTypeDescription,
}, {
Name: "8",
Description: "When clicking submit your patreon pledge will be linked " +
"to your pixeldrain account and you will be able to use " +
"pixeldrain's premium features. If you would like to update or " +
"cancel your subscription later on you can do so through " +
"patreon's dashboard",
Type: FieldTypeDescription,
}}
if f.ReadInput(r) {
if err := td.PixelAPI.PatreonLink(r.FormValue("key")); err != nil {
formAPIError(err, &f)
} else {
// Request was a success
f.SubmitSuccess = true
f.SubmitMessages = []template.HTML{template.HTML(
"Success! Your account has been upgraded to the " + patron.Subscription.Name + " plan.",
)}
}
}
return f
}

View File

@@ -217,83 +217,3 @@ func (wc *WebController) usernameForm(td *TemplateData, r *http.Request) (f Form
}
return f
}
func (wc *WebController) patreonLinkForm(td *TemplateData, r *http.Request) (f Form) {
f.Name = "link_patreon_subscription"
f.Title = "Link Patreon pledge to pixeldrain account"
f.SubmitLabel = "Submit"
if r.FormValue("key") == "" {
f.Submitted = true
f.SubmitMessages = []template.HTML{"Patron ID not found"}
return f
}
patron, err := td.PixelAPI.PatreonByID(r.FormValue("key"))
if err != nil && err.Error() == "not_found" {
f.Submitted = true
f.SubmitMessages = []template.HTML{"Patron ID not found"}
return f
} else if err != nil {
f.Submitted = true
formAPIError(err, &f)
return f
}
f.Fields = []Field{{
Name: "1",
Label: "",
DefaultValue: "",
Description: "<h3>Please confirm that the following information is correct:</h3>",
Type: FieldTypeDescription,
}, {
Name: "2",
Label: "Pixeldrain username",
DefaultValue: td.User.Username,
Type: FieldTypeDescription,
}, {
Name: "3",
Label: "Pixeldrain e-mail",
DefaultValue: td.User.Email,
Type: FieldTypeDescription,
}, {
Name: "4",
Label: "Patreon username",
DefaultValue: patron.FullName,
Type: FieldTypeDescription,
}, {
Name: "5",
Label: "Patreon e-mail",
DefaultValue: patron.UserEmail,
Type: FieldTypeDescription,
}, {
Name: "6",
Label: "Subscription name",
DefaultValue: patron.Subscription.Name,
Type: FieldTypeDescription,
}, {
Name: "7",
Label: "Monthly contribution",
DefaultValue: fmt.Sprintf("€ %.2f / month", float64(patron.PledgeAmountCents)/100.0),
Type: FieldTypeDescription,
}, {
Name: "8",
Description: "When clicking submit your patreon pledge will be linked " +
"to your pixeldrain account and you will be able to use " +
"pixeldrain's premium features. If you would like to update or " +
"cancel your subscription later on you can do so through " +
"patreon's dashboard",
Type: FieldTypeDescription,
}}
if f.ReadInput(r) {
if err := td.PixelAPI.PatreonLink(r.FormValue("key")); err != nil {
formAPIError(err, &f)
} else {
// Request was a success
f.SubmitSuccess = true
f.SubmitMessages = []template.HTML{template.HTML("Success!")}
}
}
return f
}

View File

@@ -208,7 +208,7 @@ var defaultPixeldrainStyle = pixeldrainStyleSheet{
TextColor: hsl{0, 0, .7},
InputColor: hsl{0, 0, .2},
InputTextColor: hsl{0, 0, 1},
HighlightColor: hsl{89, .51, .45},
HighlightColor: hsl{89, .60, .45},
HighlightTextColor: hsl{0, 0, 0},
DangerColor: hsl{339, .65, .31},
ScrollbarForegroundColor: hsl{0, 0, .35},