Skip to content

Commit

Permalink
Merge pull request #55 from Moros1138/patreon-and-analytics
Browse files Browse the repository at this point in the history
Patreon and analytics
  • Loading branch information
Moros1138 authored May 6, 2024
2 parents c5dfbd4 + a2805bf commit 235e34b
Show file tree
Hide file tree
Showing 12 changed files with 288 additions and 27 deletions.
28 changes: 5 additions & 23 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ APP_FAKER_LOCALE=en_US
APP_MAINTENANCE_DRIVER=file
APP_MAINTENANCE_STORE=database

# compiler environment: nsjail, or local (default)
COMPILER_ENVIRONMENT=nsjail
# compiler caching: true or false (default)
COMPILER_CACHING=true

BCRYPT_ROUNDS=12
Expand All @@ -25,11 +23,6 @@ LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=laravel
# DB_USERNAME=root
# DB_PASSWORD=

SESSION_DRIVER=database
SESSION_LIFETIME=120
Expand All @@ -44,26 +37,15 @@ QUEUE_CONNECTION=database
CACHE_STORE=database
CACHE_PREFIX=

MEMCACHED_HOST=127.0.0.1

REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=log
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="[email protected]"
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

VITE_APP_NAME="${APP_NAME}"

PATREON_ACCESS_TOKEN=
PATREON_WEBHOOK_SECRET=

CLOUDFLARE_ANALYTICS_TOKEN=
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. Each batch

It is a summary of changes that would be pertinent to the end user of the PGEtinker website. For a comprehensive history of changes made to the project, please refer to the repository's commit history.

## 2024-05-06

- Added cloudflare analytics and disclosure
- Added supporter wall

## 2024-05-05

- Added logging to database
Expand Down
42 changes: 42 additions & 0 deletions app/Console/Commands/Patreon.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace App\Console\Commands;

use App\Http\Controllers\PatreonController;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;

class Patreon extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:patreon';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Get Patreon Supporters';

/**
* Execute the console command.
*/
public function handle()
{
if(empty(env("PATREON_ACCESS_TOKEN")))
{
Log::error("Error: missing Patreon Access Token... aborted.");
return;
}

$controller = new PatreonController();
$controller->getPatreonNames();

}
}
101 changes: 101 additions & 0 deletions app/Http/Controllers/PatreonController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

namespace App\Http\Controllers;

use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;

class PatreonController extends Controller
{
function update(Request $request)
{
$disk = (!empty(env("AWS_BUCKET"))) ? Storage::disk("s3") : Storage::disk("local");

if(empty(env("PATREON_ACCESS_TOKEN")) || empty(env("PATREON_WEBHOOK_SECRET")))
{
Log::error("Error: missing Patreon Access Token or Webhook Secret... aborted.");

return response([
"statusCode" => 500,
"message" => "Missing Patreon Access Token or Webhook Secret.",
], 500);
}

$signature = hash_hmac("md5", $request->getContent(), env("PATREON_WEBHOOK_SECRET"));
if($request->header("X-Patreon-Signature") != $signature)
{
Log::alert("Unauthorized webhook request");
return response([
"statusCode" => 401,
"message" => "unauthorized"
]);
}

$this->getPatreonNames();

return [];
}

function getPatreonNames()
{
$disk = (!empty(env("AWS_BUCKET"))) ? Storage::disk("s3") : Storage::disk("local");

Log::info("Getting Patreon Supporters");

$campaign = Http::withToken(env("PATREON_ACCESS_TOKEN"))
->get("https://www.patreon.com/api/oauth2/v2/campaigns")
->json()["data"][0]["id"];

$cursor = null;
$keepGoing = true;

$supporters = [];
while($keepGoing)
{
$membersRequest = Http::withToken(env("PATREON_ACCESS_TOKEN"));
$membersRequest->withQueryParameters([
"page[count]" => 25,
"include" => "currently_entitled_tiers",
"fields[member]" => "full_name,last_charge_date,last_charge_status,currently_entitled_amount_cents,patron_status",
]);
if($cursor != null)
{
$membersRequest->withQueryParameters([
"page[cursor]" => $cursor,
]);
}

$members = $membersRequest->get("https://www.patreon.com/api/oauth2/v2/campaigns/{$campaign}/members")->json();

if(count($members["data"]) > 0)
{
foreach($members["data"] as $member)
{
if($member["attributes"]["currently_entitled_amount_cents"] >= 500)
{
if(!empty($member["attributes"]["full_name"]))
{
$supporters[] = [
"amount" => $member["attributes"]["currently_entitled_amount_cents"],
"name" => $member["attributes"]["full_name"],
];
}
}
}
}

$cursor = $members["meta"]["pagination"]["cursors"]["next"];
if(empty($cursor))
{
$keepGoing = false;
}
}

$disk->put("supporters.json", json_encode(["supporters" => $supporters]));
}
}


30 changes: 30 additions & 0 deletions resources/css/dialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,33 @@
content: "✔ Fixed: ";
color: rgb(252, 252, 170);
}

.dialog.supporters h3 {
text-align: center;
font-size: 2rem;
// text-decoration: underline;
padding-bottom: 1rem;
border-bottom: 4px solid var(--dialog-text-color);
}

.dialog.supporters .names {
display: flex;
width: 100%;
flex-direction: column;
justify-content: center;
// justify-items: center;
align-items: center;
}

.dialog.supporters .names .name {
padding: .5rem 2rem;
font-size: 2.5rem;
}

.dialog.supporters a {
display: block;
text-align: center;
margin-top: 2rem;
margin-bottom: 1rem;
font-size: 2.5rem;
}
3 changes: 2 additions & 1 deletion resources/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import agreeDialog from './lib/agreeDialog';
import shareDialog from './lib/shareDialog';
import newsDialog from './lib/newsDialog';
import defaultLayout from './lib/defaultLayout';
import supportersDialog from './lib/supportersDialog';

class PGEtinker
{
Expand Down Expand Up @@ -192,7 +193,7 @@ class PGEtinker
document.querySelector("#supporters").addEventListener("click", (event) =>
{
event.preventDefault();
alert("Not Implemented");
supportersDialog();
});

document.querySelector("#news-and-updates").addEventListener("click", (event) =>
Expand Down
8 changes: 7 additions & 1 deletion resources/js/lib/agreeDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ export default function agreeDialog()
<li>
Share your code worldwide. This only applies if you
use the "Share" functionality.
</li>
</li>
<li>
To use <a href="https://developers.cloudflare.com/analytics/web-analytics/" target="_blank">
passive monitoring analytics</a> for the purpose
of identifying problems with the app and improving
the overall experience.
</li>
</ul>
</div>
<div class="footer">
Expand Down
66 changes: 66 additions & 0 deletions resources/js/lib/supportersDialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
export default function supportersDialog()
{
function supportersClickAnywhereHandler(event)
{
let supportersDialog = document.querySelector(".dialog.supporters");
if(supportersDialog == null)
return;

if(event.target.tagName == 'A')
return;

supportersDialog.dispatchEvent(new Event("close-dialog"));
}

return new Promise((resolve) =>
{
let supportersDialog = document.createElement("div");

supportersDialog.classList.toggle("dialog", true);
supportersDialog.classList.toggle("supporters", true);

axios.get("/api/supporters").then((response) =>
{

let entries = [];

if(response.data.supporters.length > 0)
{
response.data.supporters.forEach((entry) =>
{
entries.push(`<div class="name">◀ ${entry} ▶</div>`);
});
}
else
{
entries.push(`<div class="name">◀ No Supporters Yet ▶</div>`);
}

supportersDialog.innerHTML = `
<div class="window">
<div class="header">Patreon Supporters!</div>
<div class="content">
<h3>PGEtinker would not exist without the support of:</h3>
<div class="names">
${entries.join('')}
</div>
<a target="_blank" href="https://patreon.com/PGEtinker">
Become a Supporter
</a>
</div>
</div>`;

supportersDialog.addEventListener("close-dialog", (event) =>
{
setTimeout(() => window.removeEventListener("click", supportersClickAnywhereHandler), 500);
supportersDialog.remove();
resolve();
});

setTimeout(() => window.addEventListener("click", supportersClickAnywhereHandler), 500);
document.body.appendChild(supportersDialog);
});

});

}
3 changes: 3 additions & 0 deletions resources/views/disagree.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,8 @@


</div>

@include("shared.analytics")

</body>
</html>
4 changes: 3 additions & 1 deletion resources/views/home.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
@vite('resources/js/app.js')
</head>
<body>

<div id="app">
<nav id="header">
<a class="brand" href="/">
Expand Down Expand Up @@ -119,5 +118,8 @@
</div>
</div>
<textarea id="code" style="display: none;">{{ $code }}</textarea>

@include("shared.analytics")

</body>
</html>
4 changes: 4 additions & 0 deletions resources/views/shared/analytics.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

@if( !empty(env("CLOUDFLARE_ANALYTICS_TOKEN")))
<!-- Cloudflare Web Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "{{ env("CLOUDFLARE_ANALYTICS_TOKEN") }}"}'></script><!-- End Cloudflare Web Analytics -->
@endif
Loading

0 comments on commit 235e34b

Please sign in to comment.