Skip to content

Commit

Permalink
add iCalendar Subscription (#636)
Browse files Browse the repository at this point in the history
  • Loading branch information
Qetesh authored Dec 6, 2024
1 parent fda9ac3 commit def6841
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 0 deletions.
57 changes: 57 additions & 0 deletions api/subscriptions/get_subscriptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,63 @@ function getPriceConverted($price, $currency, $database)
$subscriptionsToReturn[] = $subscriptionToReturn;
}

if (isset($_REQUEST['type'])) {
$type = $_REQUEST['type'];
$stmt->bindValue(':inactive', false, SQLITE3_INTEGER);
$result = $stmt->execute();

if ($type == "iCalendar") {
header('Content-Type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="subscriptions.ics"');

if ($result === false) {
die("BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:NAME:\nEND:VCALENDAR");
}

$icsContent = "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//Wallos//$type//EN\nNAME:Wallos\nX-WR-CALNAME:Wallos\n";

while ($subscription = $result->fetchArray(SQLITE3_ASSOC)) {
$subscription['payer_user'] = $members[$subscription['payer_user_id']];
$subscription['category'] = $categories[$subscription['category_id']];
$subscription['payment_method'] = $paymentMethods[$subscription['payment_method_id']];
$subscription['currency'] = $currencies[$subscription['currency_id']]['symbol'];
$subscription['trigger'] = $subscription['notify_days_before'] ? $subscription['notify_days_before'] : 1;
$subscription['price'] = number_format($subscription['price'], 2);

$uid = uniqid();
$summary = "Wallos: " . $subscription['name'];
$description = "Price: {$subscription['currency']}{$subscription['price']}\\nCategory: {$subscription['category']}\\nPayment Method: {$subscription['payment_method']}\\nPayer: {$subscription['payer_user']}\\nNotes: {$subscription['notes']}";
$dtstart = (new DateTime($subscription['next_payment']))->format('Ymd\THis\Z');
$dtend = (new DateTime($subscription['next_payment']))->modify('+1 hour')->format('Ymd\THis\Z');
$location = isset($subscription['url']) ? $subscription['url'] : '';
$alarm_trigger = '-' . $subscription['trigger'] . 'D';

$icsContent .= <<<ICS
BEGIN:VEVENT
UID:$uid
SUMMARY:$summary
DESCRIPTION:$description
DTSTART:$dtstart
DTEND:$dtend
LOCATION:$location
STATUS:CONFIRMED
TRANSP:OPAQUE
BEGIN:VALARM
ACTION:DISPLAY
DESCRIPTION:Reminder
TRIGGER:$alarm_trigger
END:VALARM
END:VEVENT
ICS;
}

$icsContent .= "END:VCALENDAR\n";
echo $icsContent;
$db->close();
exit;
}
}

$response = [
"success" => true,
Expand Down
45 changes: 45 additions & 0 deletions calendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,51 @@ function getPriceConverted($price, $currency, $database, $userId)
?>
<div class="split-header">
<h2>Calendar</h2>
<button class="button tiny" onClick="showExportPopup()" style="margin-right: auto"> <?= translate('subscriptions', $i18n) ?> </button>
<div id="subscriptions_calendar" class="subscription-modal">
<div class="modal-header">
<h3><?= translate('subscriptions', $i18n) ?></h3>
<span class="fa-solid fa-xmark close-modal" onclick="closePopup()"></span>
</div>
<div class="form-group-inline">
<input id="iCalendarUrl" type="text" value="" readonly>
<button onclick="copyToClipboard()" class="button tiny"> <?= translate('copy_to_clipboard', $i18n) ?> </button>
</div>
</div>

<script>
function showExportPopup() {
const host = window.location.origin;
const apiPath = "/api/subscriptions/get_subscriptions.php";
const apiKey = "<?= $userData['api_key'] ?>";
const queryParams = `?api_key=${apiKey}&type=iCalendar`;
const fullUrl = `${host}${apiPath}${queryParams}`;
document.getElementById('iCalendarUrl').value = fullUrl;

if (apiKey === "") {
showErrorMessage( "<?= translate('invalid_api_key', $i18n) ?>" );
return;
}
document.getElementById('subscriptions_calendar').classList.add('is-open');
}
function closePopup() {
document.getElementById('subscriptions_calendar').classList.remove('is-open');
}

function copyToClipboard() {
const urlField = document.getElementById('iCalendarUrl');
urlField.select();
urlField.setSelectionRange(0, 99999); // For mobile devices
navigator.clipboard.writeText(urlField.value)
.then(() => {
showSuccessMessage(translate('copied_to_clipboard'));
})
.catch(() => {
showErrorMessage(translate('unknown_error'));
});
}
</script>

<div class="calendar-nav">
<?php
if (!$sameAsCurrent) {
Expand Down

0 comments on commit def6841

Please sign in to comment.