mark tankbuster as purple (superbolide is broken)

move stuff to env file and recommit config.php
This commit is contained in:
Akurosia Kamo 2026-05-24 09:31:57 +02:00
parent eecab6d76a
commit 243cb0608c
6 changed files with 109 additions and 15 deletions

6
.env.example Normal file
View File

@ -0,0 +1,6 @@
DEV_MODE=true
CLIENT_ID=your-fflogs-client-id
REDIRECT_URI=http://localhost:8080/auth/callback.php
AUTHORIZE_URI=https://www.fflogs.com/oauth/authorize
TOKEN_URI=https://www.fflogs.com/oauth/token
GRAPHQL_URI=https://www.fflogs.com/api/v2/user

2
.gitignore vendored
View File

@ -1,5 +1,5 @@
.claude/
debug/
cached_logs/
.env
fflogs-schema.json
config.php

View File

@ -1,11 +1,51 @@
<?php
define('DEV_MODE', true); // set to false in production
define('CLIENT_ID', 'a1d27cba-b7f8-48dd-aefd-4697b457cc67');
define('REDIRECT_URI', 'http://localhost:8080/auth/callback.php');
define('AUTHORIZE_URI','https://www.fflogs.com/oauth/authorize');
define('TOKEN_URI', 'https://www.fflogs.com/oauth/token');
define('GRAPHQL_URI', 'https://www.fflogs.com/api/v2/user');
function load_env_file(string $path): void {
if (!is_file($path)) return;
foreach (file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [] as $line) {
$line = trim($line);
if ($line === '' || str_starts_with($line, '#')) continue;
[$key, $value] = array_pad(explode('=', $line, 2), 2, '');
$key = trim($key);
if ($key === '') continue;
$value = trim($value);
if (
strlen($value) >= 2
&& (($value[0] === '"' && $value[-1] === '"') || ($value[0] === "'" && $value[-1] === "'"))
) {
$value = substr($value, 1, -1);
}
$_ENV[$key] = $value;
putenv($key . '=' . $value);
}
}
function env_value(string $key, ?string $default = null): string {
$value = $_ENV[$key] ?? getenv($key);
if ($value === false || $value === null || $value === '') {
if ($default !== null) return $default;
throw new RuntimeException('Missing required environment value: ' . $key);
}
return (string)$value;
}
function env_bool(string $key, bool $default = false): bool {
$value = strtolower(env_value($key, $default ? 'true' : 'false'));
return in_array($value, ['1', 'true', 'yes', 'on'], true);
}
load_env_file(__DIR__ . '/.env');
define('DEV_MODE', env_bool('DEV_MODE'));
define('CLIENT_ID', env_value('CLIENT_ID'));
define('REDIRECT_URI', env_value('REDIRECT_URI'));
define('AUTHORIZE_URI', env_value('AUTHORIZE_URI'));
define('TOKEN_URI', env_value('TOKEN_URI'));
define('GRAPHQL_URI', env_value('GRAPHQL_URI'));
function session_start_safe(): void {
if (session_status() === PHP_SESSION_NONE) {
@ -19,3 +59,38 @@ function session_start_safe(): void {
session_start();
}
}
function default_return_path(): string {
$script = str_replace('\\', '/', $_SERVER['SCRIPT_NAME'] ?? '/index.php');
$base = rtrim(dirname(dirname($script)), '/');
return ($base === '' ? '' : $base) . '/index.php';
}
function safe_return_path(?string $value): string {
$value = trim((string)$value);
if ($value === '') return default_return_path();
$parts = parse_url($value);
if ($parts === false) return default_return_path();
if (isset($parts['host'])) {
$currentHost = strtolower(explode(':', $_SERVER['HTTP_HOST'] ?? '')[0]);
if (strtolower($parts['host']) !== $currentHost) return default_return_path();
} elseif (str_starts_with($value, '//')) {
return default_return_path();
}
$path = $parts['path'] ?? '';
if ($path === '') $path = default_return_path();
if ($path[0] !== '/') $path = '/' . ltrim($path, '/');
$query = isset($parts['query']) ? '?' . $parts['query'] : '';
return $path . $query;
}
function current_return_path(): string {
return safe_return_path($_SERVER['REQUEST_URI'] ?? null);
}
function auth_start_href(?string $returnPath = null): string {
return 'auth/start.php?return=' . rawurlencode($returnPath ?? current_return_path());
}

View File

@ -797,6 +797,11 @@
z-index: 1;
}
.timeline-hit-line--tankbuster {
width: 2px;
background: rgba(177,112,255,.62);
}
.timeline-player-row .timeline-track {
background-color: rgba(255,255,255,0.015);
}
@ -874,6 +879,17 @@
background: rgba(224,92,92,.22);
}
.timeline-boss-action--tankbuster {
border-color: rgba(177,112,255,.55);
background: rgba(177,112,255,.18);
color: #dbc7ff;
}
.timeline-boss-action--tankbuster:hover {
border-color: rgba(177,112,255,.85);
background: rgba(177,112,255,.28);
}
.timeline-mitigation {
position: absolute;
top: 6px;

View File

@ -2,11 +2,6 @@
require_once __DIR__ . '/config.php';
session_start_safe();
function auth_start_href(): string {
$return = $_SERVER['REQUEST_URI'] ?? '/';
return 'auth/start.php?return=' . urlencode($return);
}
$authenticated = !empty($_SESSION['access_token'])
&& ($_SESSION['token_expires'] ?? 0) > time();

View File

@ -920,14 +920,14 @@ function renderTimelineHtml(plan) {
const bossActions = layoutBossActions(mechanics, duration);
const laneCount = Math.max(1, ...bossActions.map(item => item.lane + 1));
const hitLines = mechanics.map(m => `
<span class="timeline-hit-line" style="left:${(m.timestamp / duration) * 100}%"></span>
<span class="timeline-hit-line${m.isHeavyTankbuster ? ' timeline-hit-line--tankbuster' : ''}" style="left:${(m.timestamp / duration) * 100}%"></span>
`).join('');
const bossItems = bossActions.map(({ mechanic: m, left, lane }) => `
<button class="timeline-boss-action"
<button class="timeline-boss-action${m.isHeavyTankbuster ? ' timeline-boss-action--tankbuster' : ''}"
style="left:${left}%;top:${8 + lane * 30}px"
data-mechanic-id="${escHtml(m.id)}"
title="${escHtml(fmtTimestamp(m.timestamp))} · ${escHtml(m.name)}">
title="${escHtml(fmtTimestamp(m.timestamp))} · ${escHtml(m.name)} · ${m.isHeavyTankbuster ? 'Tankbuster' : 'AoE'}">
${escHtml(m.name)}
</button>
`).join('');
@ -1869,6 +1869,7 @@ function aoeEventsToMechanics(aoeEvents, fightStart, phases, players, withMitiga
timestamp: relTs,
phase: phase?.name ?? '',
unmitigatedDamage: avgUnmit,
isHeavyTankbuster: !!ev.isHeavyTankbuster,
notes: '',
assignments,
};
@ -1991,6 +1992,7 @@ async function refreshPlanLanguage(planId) {
...mechanic,
name: match.abilityName ?? mechanic.name,
abilityId: match.abilityId ?? mechanic.abilityId,
isHeavyTankbuster: !!match.isHeavyTankbuster,
assignments,
};
});