summaryrefslogtreecommitdiff
path: root/public/channels
diff options
context:
space:
mode:
Diffstat (limited to 'public/channels')
-rw-r--r--public/channels/index.php372
1 files changed, 372 insertions, 0 deletions
diff --git a/public/channels/index.php b/public/channels/index.php
new file mode 100644
index 0000000..b32b63b
--- /dev/null
+++ b/public/channels/index.php
@@ -0,0 +1,372 @@
+<?php
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/partials.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../lib/utils.php';
+include_once $_SERVER['DOCUMENT_ROOT'] . '/../config.php';
+
+function get_twitch_users(string $ids): array
+{
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, "https://api.twitch.tv/helix/users?id=$ids");
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
+ 'Authorization: Bearer ' . TWITCH_AUTHORIZATION_TOKEN,
+ 'Client-Id: ' . TWITCH_CLIENT_ID
+ ]);
+ curl_setopt($ch, CURLOPT_HEADER, 0);
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+
+ $response = curl_exec($ch);
+ $response = json_decode($response, true);
+
+ curl_close($ch);
+
+ return $response['data'] ?? [];
+}
+
+$channel = null;
+$channels = [];
+
+$db = new PDO(DB_URL, DB_USER, DB_PASS);
+
+if (isset($_GET['alias_id'])) {
+ $stmt = $db->prepare('SELECT c.*, cp.*, array_to_json(cp.features) as features
+ FROM channels c
+ LEFT JOIN channel_preferences cp ON cp.id = c.id
+ WHERE c.alias_id = ?
+ ');
+ $stmt->execute([$_GET['alias_id']]);
+ $channel = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
+
+ if (!isset($channel)) {
+ http_response_code(404);
+ exit;
+ }
+
+ $channel['features'] = json_decode($channel['features'] ?: '[]', true);
+
+ // fetching custom commands
+ $stmt = $db->prepare('SELECT *, array_to_json(messages) as messages
+ FROM custom_commands
+ WHERE channel_id = ?
+ ORDER BY created_at DESC
+ ');
+ $stmt->execute([$channel['id']]);
+ $channel['commands'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ foreach ($channel['commands'] as &$c) {
+ $c['messages'] = json_decode($c['messages'], true);
+ }
+ unset($c);
+
+ // fetching timers
+ $stmt = $db->prepare('SELECT *, array_to_json(messages) as messages
+ FROM timers
+ WHERE channel_id = ?
+ ');
+ $stmt->execute([$channel['id']]);
+ $channel['timers'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
+ foreach ($channel['timers'] as &$c) {
+ $c['messages'] = json_decode($c['messages'], true);
+ }
+ unset($c);
+
+ // fetching events
+ $stmt = $db->prepare('SELECT e.*, array_to_json(e.flags) as flags, COUNT(es.id) as subscription_count
+ FROM events e
+ LEFT JOIN event_subscriptions es ON es.event_id = e.id
+ WHERE e.channel_id = ?
+ GROUP BY e.id
+ ORDER BY subscription_count DESC
+ ');
+ $stmt->execute([$channel['id']]);
+ $channel['events'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
+
+ // fetching event names
+ $twitch_types = ['live', 'offline', 'title', 'category'];
+ $channel_ids = [];
+ foreach ($channel['events'] as &$e) {
+ $e['flags'] = json_decode($e['flags'], true);
+ if (in_array($e['event_type'], $twitch_types)) {
+ array_push($channel_ids, $e['target_alias_id']);
+ }
+ }
+ unset($e);
+ if (!empty($channel_ids)) {
+ $event_users = get_twitch_users(implode('&id=', $channel_ids));
+ foreach ($event_users as $user) {
+ foreach ($channel['events'] as &$e) {
+ if ($e['target_alias_id'] == $user['id']) {
+ $e['name'] = $user['login'];
+ }
+ }
+ unset($e);
+ }
+ }
+
+ // translating features
+ foreach ($channel['features'] as &$f) {
+ if ($f == "notify_7tv_updates") {
+ $f = "7TV Updates";
+ }
+ }
+ unset($f);
+
+ if ($response = get_twitch_users($channel['alias_id'])) {
+ $user = $response[0];
+ $channel['pfp'] = $user['profile_image_url'];
+ $channel['description'] = $user['description'] ?: null;
+ }
+
+ $has_content = !empty($channel['events']) || !empty($channel['commands']) || !empty($channel['timers']);
+} else if (!SHOW_CHANNEL_LIST) {
+ http_response_code(403);
+ exit;
+} else {
+ $stmt = $db->query('SELECT alias_id, alias_name FROM channels WHERE opt_outed_at IS NULL ORDER BY joined_at DESC');
+ $stmt->execute();
+
+ $channels = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
+}
+
+// fetching user pfps
+if (!empty($channels)) {
+ $channel_ids = [];
+ foreach ($channels as $c) {
+ array_push($channel_ids, $c['alias_id']);
+ }
+
+ $response = get_twitch_users(implode('&id=', $channel_ids));
+
+ if (!empty($response)) {
+ foreach ($response as $c) {
+ $index = array_search($c['id'], array_column($channels, 'alias_id'));
+ $channels[$index]['pfp'] = $c['profile_image_url'];
+ }
+ }
+}
+?>
+
+<html>
+
+<head>
+ <title>Channels - The Tinybot Project</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
+ <link rel="stylesheet" href="/static/style.css">
+ <link rel="shortcut icon" href="/static/favicon.ico" type="image/x-icon">
+</head>
+
+<body>
+ <main>
+ <?php html_navigation_bar() ?>
+ <content class="gap-16">
+ <?php if (isset($channel)): ?>
+ <section class="card row p-16">
+ <?php if (isset($channel['pfp'])): ?>
+ <div class="icon">
+ <img src="<?= $channel['pfp'] ?>" alt="">
+ </div>
+ <?php endif; ?>
+ <div class="column gap-8 grow">
+ <h1>About <?= $channel['alias_name'] ?></h1>
+ <?php if (isset($channel['description'])): ?>
+ <p><i><?= $channel['description'] ?></i></p>
+ <?php endif; ?>
+ <div class="row gap-16 font-small">
+ <p>Language: <img src="/static/img/icons/flags/<?= $channel['language'] ?>.png" alt="">
+ <?= ucfirst($channel['language']) ?></p>
+ <p>Prefix: <b><?= $channel['prefix'] ?></b></p>
+ </div>
+ <?php if (!empty($channel['features'])): ?>
+ <div class="row gap-16 font-small">
+ <p>Features: <b><?= implode(', ', $channel['features']) ?></b></p>
+ </div>
+ <?php endif; ?>
+ </div>
+ <div class="column gap-8">
+ <p><img src="/static/img/icons/door_in.png" alt=""> Joined
+ <?= format_timestamp(time() - strtotime($channel['joined_at'])) ?> ago
+ </p>
+ <?php if (isset($channel['opt_outed_at'])): ?>
+ <p class="red box text-center"><img src="/static/img/icons/door_out.png" alt=""> Opted out!</p>
+ <?php endif; ?>
+ </div>
+ </section>
+
+ <!-- CHANNEL CONTENT -->
+ <?php if ($has_content): ?>
+ <section class="box" id="channel-content">
+ <div class="tabs row gap-8" id="channel-content-tabs" style="display: none">
+ <?php if (!empty($channel['events'])): ?>
+ <button class="tab" id="events-button">Events</button>
+ <?php endif; ?>
+ <?php if (!empty($channel['commands'])): ?>
+
+ <button class="tab" id="commands-button">Custom commands</button>
+ <?php endif; ?>
+
+ <?php if (!empty($channel['timers'])): ?>
+
+ <button class="tab" id="timers-button">Timers</button>
+ <?php endif; ?>
+
+ </div>
+ <div class="content">
+ <?php if (!empty($channel['events'])): ?>
+ <!-- Events -->
+ <div class="tab-content column" id="events">
+ <h2>Events</h2>
+ <hr>
+ <table>
+ <tr>
+ <th>Name</th>
+ <th>Type</th>
+ <th>Message</th>
+ <th>Flags</th>
+ <th>Subscribers</th>
+ </tr>
+ <?php foreach ($channel['events'] as $e): ?>
+ <tr>
+ <td>
+ <?php if (in_array($e['event_type'], $twitch_types)): ?>
+ <a href="https://twitch.tv/<?= $e['name'] ?>"><?= $e['name'] ?></a>
+ <?php elseif ($e['event_type'] == 'github'): ?>
+ <a
+ href="https://github.com/<?= $e['custom_alias_id'] ?>"><?= $e['custom_alias_id'] ?></a>
+ <?php else: ?>
+ <?= $e['custom_alias_id'] ?>
+ <?php endif; ?>
+ </td>
+ <td><?= $e['event_type'] ?></td>
+ <td><?= $e['message'] ?></td>
+ <td>
+ <?= empty($e['flags']) ? '-' : implode(', ', $e['flags']) ?>
+ </td>
+ <td><?= $e['subscription_count'] ?></td>
+ </tr>
+ <?php endforeach; ?>
+ </table>
+ </div>
+ <?php endif; ?>
+
+ <?php if (!empty($channel['commands'])): ?>
+ <!-- Commands -->
+ <div class="tab-content column" id="commands">
+ <h2>Custom commands</h2>
+ <hr>
+ <table>
+ <tr>
+ <th>Name</th>
+ <th>Messages</th>
+ <th>Last executed</th>
+ </tr>
+ <?php foreach ($channel['commands'] as $c): ?>
+ <tr>
+ <td><?= $c['name'] ?></td>
+ <td class="column">
+ <?php foreach ($c['messages'] as $m): ?>
+ <p><?= $m ?></p>
+ <?php endforeach; ?>
+ </td>
+ <td><?= isset($c['last_executed_at']) ? format_timestamp(time() - strtotime($c['last_executed_at'])) . ' ago' : '-' ?>
+ </td>
+ </tr>
+ <?php endforeach; ?>
+ </table>
+ </div>
+ <?php endif; ?>
+
+ <?php if (!empty($channel['timers'])): ?>
+ <!-- Timers -->
+ <div class="tab-content column" id="timers">
+ <h2>Timers</h2>
+ <hr>
+ <table>
+ <tr>
+ <th>Name</th>
+ <th>Messages</th>
+ <th>Interval</th>
+ <th>Last executed</th>
+ </tr>
+ <?php foreach ($channel['timers'] as $t): ?>
+ <tr>
+ <td><?= $t['name'] ?></td>
+ <td class="column">
+ <?php foreach ($t['messages'] as $m): ?>
+ <p><?= $m ?></p>
+ <?php endforeach; ?>
+ </td>
+ <td><?= format_timestamp($t['interval_sec']) ?></td>
+ <td><?= format_timestamp(time() - strtotime($t['last_executed_at'])) ?> ago</td>
+ </tr>
+ <?php endforeach; ?>
+ </table>
+ </div>
+ <?php endif; ?>
+ </div>
+ </section>
+ <?php else: ?>
+ <p class="text-center"><i>Nothing found...</i></p>
+ <?php endif; ?>
+ <?php elseif (empty($channels)): ?>
+ <section class="column justify-center align-center background-colorful p-24">
+ <h1>No one has joined yet... &semi;&lpar;</h1>
+ <a href="/!join">Be the first one&excl;</a>
+ </section>
+ <?php else: ?>
+ <section class="column justify-center align-center background-colorful p-24">
+ <h1><?= count($channels) ?> channels have already joined us</h1>
+ <a href="/!join">Check out the &excl;join command to participate&excl;</a>
+ </section>
+ <section class="grid-4 gap-16">
+ <?php foreach ($channels as $c): ?>
+ <a href="/channels/?alias_id=<?= $c['alias_id'] ?>" class="card justify-center align-center">
+ <div class="icon">
+ <img src="<?= $c['pfp'] ?? '/static/img/default_avatar.webp' ?>" alt="">
+ </div>
+ <p><b><?= $c['alias_name'] ?></b></p>
+ </a>
+ <?php endforeach; ?>
+ </section>
+ <?php endif; ?>
+ </content>
+ </main>
+
+ <?php html_footer() ?>
+</body>
+
+<?php if (isset($channel) && $has_content): ?>
+ <script>
+ for (const elem of document.querySelectorAll('#channel-content h2, #channel-content hr')) {
+ elem.remove();
+ }
+
+ document.getElementById('channel-content-tabs').style.display = 'flex';
+
+ const tabButtons = document.querySelectorAll('#channel-content-tabs button');
+ const tabContent = document.querySelectorAll('.tab-content');
+
+ function enableTab(name) {
+ tabButtons.forEach(x => {
+ if (x.getAttribute('id') == name + '-button') {
+ x.setAttribute('disabled', '');
+ } else {
+ x.removeAttribute('disabled');
+ }
+ });
+
+ tabContent.forEach(x => {
+ x.style.display = x.getAttribute('id') == name ? 'flex' : 'none';
+ });
+ }
+
+ enableTab(tabButtons[0].getAttribute('id').split('-')[0]);
+
+ for (const tabButton of tabButtons) {
+ const id = tabButton.getAttribute('id');
+ const name = id.split('-')[0];
+ tabButton.addEventListener('click', () => enableTab(name));
+ }
+ </script>
+<?php endif; ?>
+
+</html> \ No newline at end of file