here2share

Claude AI Chat

Jul 21st, 2024
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <html><head><base href="https://claude.ai"><title>Claude AI Chat</title>
  2. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.css">
  3. <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/codemirror.min.js"></script>
  4. <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/javascript/javascript.min.js"></script>
  5. <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/python/python.min.js"></script>
  6. <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/xml/xml.min.js"></script>
  7. <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.2/mode/css/css.min.js"></script>
  8. <style>
  9.   /* Styles remain unchanged */
  10.   body, html {
  11.     font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
  12.     line-height: 1.5;
  13.     color: #343541;
  14.     margin: 0;
  15.     padding: 0;
  16.     height: 100%;
  17.     overflow: hidden;
  18.   }
  19.   .container {
  20.     display: flex;
  21.     height: 100vh;
  22.   }
  23.   .sidebar {
  24.     width: 50%;
  25.     max-width: 120px;
  26.     background-color: #f7f7f8;
  27.     border-right: 1px solid #e5e5e5;
  28.     padding: 5px;
  29.     overflow-y: auto;
  30.   }
  31.   .main-content {
  32.     flex-grow: 1;
  33.     display: flex;
  34.     flex-direction: column;
  35.     background-color: #ffffff;
  36.   }
  37.   .chat-window {
  38.     flex-grow: 1;
  39.     overflow-y: auto;
  40.     padding: 5px;
  41.   }
  42.   .message {
  43.     width: 100%;
  44.     max-width: 1080px;
  45.     margin-bottom: 5px;
  46.     padding: 5px 5px;
  47.     border-radius: 5px;
  48.     line-height: 1.4;
  49.   }
  50.   .user-message {
  51.     background-color: #f0f6ff;
  52.     color: #000000;
  53.     align-self: flex-end;
  54.     margin-left: auto;
  55.   }
  56.   .ai-message {
  57.     background-color: #f7f7f8;
  58.     color: #000000;
  59.   }
  60.   .input-area {
  61.     background-color: #ffffff;
  62.     padding: 5px;
  63.     border-top: 1px solid #e5e5e5;
  64.     display: flex;
  65.     justify-content: space-between;
  66.     align-items: center;
  67.     flex-wrap: wrap;
  68.   }
  69.   .user-input {
  70.     flex-grow: 1;
  71.     min-width: 1080;
  72.     padding: 5px;
  73.     border-radius: 5px;
  74.     border: 1px solid #e5e5e5;
  75.     background-color: #ffffff;
  76.     color: #000000;
  77.     font-size: 16px;
  78.     resize: none;
  79.   }
  80.   .sidebar h2 {
  81.     color: #000000;
  82.     font-size: 20px;
  83.     margin-bottom: 5px;
  84.   }
  85.   .sidebar ul {
  86.     list-style-type: none;
  87.     padding: 0;
  88.   }
  89.   .sidebar li {
  90.     margin-bottom: 5px;
  91.   }
  92.   .sidebar a {
  93.     color: #000000;
  94.     text-decoration: none;
  95.     cursor: pointer;
  96.   }
  97.   .error-message {
  98.     color: #ff4444;
  99.     margin-top: 5px;
  100.   }
  101.   .new-chat-btn, .upload-btn {
  102.     background-color: #10a37f;
  103.     color: white;
  104.     border: none;
  105.     padding: 5px;
  106.     border-radius: 5px;
  107.     cursor: pointer;
  108.     width: 100%;
  109.     margin-bottom: 5px;
  110.   }
  111.   .loading {
  112.     display: none;
  113.     text-align: center;
  114.     padding: 5px;
  115.   }
  116.   .loading::after {
  117.     content: '...';
  118.     animation: dots 1s steps(5, end) infinite;
  119.   }
  120.   @keyframes dots {
  121.     0%, 20% {
  122.       color: rgba(0,0,0,0);
  123.       text-shadow:
  124.         .25em 0 0 rgba(0,0,0,0),
  125.         .5em 0 0 rgba(0,0,0,0);
  126.     }
  127.     40% {
  128.       color: #000;
  129.       text-shadow:
  130.         .25em 0 0 rgba(0,0,0,0),
  131.         .5em 0 0 rgba(0,0,0,0);
  132.     }
  133.     60% {
  134.       text-shadow:
  135.         .25em 0 0 #000,
  136.         .5em 0 0 rgba(0,0,0,0);
  137.     }
  138.     80%, 100% {
  139.       text-shadow:
  140.         .25em 0 0 #000,
  141.         .5em 0 0 #000;
  142.     }
  143.   }
  144.   .CodeMirror {
  145.     height: auto;
  146.     border: 1px solid #eee;
  147.     margin-bottom: 5px;
  148.   }
  149.   #file-input {
  150.     display: none;
  151.   }
  152.   .cancel-btn {
  153.     background-color: #ff4444;
  154.     color: white;
  155.     border: none;
  156.     padding: 5px;
  157.     border-radius: 5px;
  158.     cursor: pointer;
  159.     margin-top: 5px;
  160.     display: none;
  161.   }
  162.   .timer-container {
  163.     display: flex;
  164.     align-items: center;
  165.     margin-top: 5px;
  166.   }
  167.   .timer {
  168.     margin-left: 5px;
  169.     font-size: 14px;
  170.     color: #666;
  171.   }
  172.   .floating-menu {
  173.     position: fixed;
  174.     background-color: #fff;
  175.     border: 1px solid #ccc;
  176.     border-radius: 10px;
  177.     padding: 5px;
  178.     z-index: 1000;
  179.   }
  180.  
  181.   .rounded-menu {
  182.     position: fixed;
  183.     background-color: #fff;
  184.     border: 1px solid #ccc;
  185.     border-radius: 10px;
  186.     padding: 5px;
  187.     z-index: 1000;
  188.     display: flex;
  189.     flex-direction: column;
  190.     align-items: center;
  191.   }
  192.  
  193.   .menu-item {
  194.     cursor: pointer;
  195.     padding: 5px;
  196.     border-radius: 10px;
  197.   }
  198.  
  199. </style>
  200. </head>
  201. <body>
  202.   <div class="container">
  203.     <div class="sidebar">
  204.       <button class="new-chat-btn" onclick="newChat()">New chat</button>
  205.       <input type="file" id="file-input" accept="*/*" onchange="uploadFile()" style="display: none;">
  206.       <button class="upload-btn" onclick="document.getElementById('file-input').click()">Upload File</button>
  207.       <h2>Recent chats</h2>
  208.       <ul id="recent-chats">
  209.         <!-- Recent chats will be dynamically added here -->
  210.       </ul>
  211.     </div>
  212.     <div class="main-content">
  213.       <div class="chat-window" id="chat-window">
  214.         <div class="message ai-message">
  215.           <p>Hello! How can I assist you today?</p>
  216.         </div>
  217.       </div>
  218.       <div class="input-area">
  219.         <form id="chat-form">
  220.           <input type="hidden" name="origin" value="https://claude.ai">
  221.           <textarea name="message" class="user-input" placeholder="Message Claude..." rows="1"></textarea>
  222.         </form>
  223.         <div class="timer-container">
  224.           <button id="cancel-btn" class="cancel-btn" style="display: none;">Cancel</button>
  225.           <div id="timer" class="timer"></div>
  226.         </div>
  227.         <div class="loading">Claude Is Thinking</div>
  228.         <div id="error-message" class="error-message"></div>
  229.       </div>
  230.     </div>
  231.   </div>
  232.  
  233.   <script>
  234.     const chatWindow = document.getElementById('chat-window');
  235.     const chatForm = document.getElementById('chat-form');
  236.     const userInput = chatForm.querySelector('textarea[name="message"]');
  237.     const loadingIndicator = document.querySelector('.loading');
  238.     const errorMessage = document.getElementById('error-message');
  239.     const recentChats = document.getElementById('recent-chats');
  240.     const cancelBtn = document.getElementById('cancel-btn');
  241.     const timerDisplay = document.getElementById('timer');
  242.  
  243.     let chatHistories = {};
  244.     let currentChatId = Date.now();
  245.     let isRequestCancelled = false;
  246.     let timerInterval;
  247.     let startTime;
  248.  
  249.     chatForm.addEventListener('submit', function(event) {
  250.       event.preventDefault();
  251.       sendMessage();
  252.     });
  253.  
  254.     cancelBtn.addEventListener('click', function() {
  255.       isRequestCancelled = true;
  256.       loadingIndicator.style.display = 'none';
  257.       cancelBtn.style.display = 'none';
  258.       clearInterval(timerInterval);
  259.       timerDisplay.textContent = '';
  260.     });
  261.  
  262.     function startTimer() {
  263.       startTime = Date.now();
  264.       timerInterval = setInterval(updateTimer, 1000);
  265.       updateTimer();
  266.     }
  267.  
  268.     function updateTimer() {
  269.       const elapsedTime = Math.floor((Date.now() - startTime) / 1000);
  270.       timerDisplay.textContent = `${elapsedTime}s`;
  271.     }
  272.  
  273.     function stopTimer() {
  274.       clearInterval(timerInterval);
  275.       timerDisplay.textContent = '';
  276.     }
  277.  
  278.     function uploadFile() {
  279.       const fileInput = document.getElementById('file-input');
  280.       const file = fileInput.files[0];
  281.       if (file) {
  282.         const reader = new FileReader();
  283.         reader.onload = function(e) {
  284.           const fileContent = e.target.result;
  285.           const fileSizeKB = Math.round(file.size / 1024);
  286.           sendFileToAI(file.name, fileContent, fileSizeKB);
  287.         };
  288.         if (file.type.startsWith('image/')) {
  289.           reader.readAsDataURL(file);
  290.         } else {
  291.           reader.readAsText(file);
  292.         }
  293.       }
  294.     }
  295.  
  296.     function sendFileToAI(fileName, fileContent, fileSizeKB) {
  297.       let messageContent;
  298.       if (fileContent.startsWith('data:image')) {
  299.         messageContent = `<action>
  300.     {
  301.       "type": "file_upload",
  302.       "name": "${fileName}",
  303.       "content_type": "${fileContent.split(';')[0].split(':')[1]}",
  304.       "base64_content": "${fileContent.split(',')[1]}",
  305.       "size_kb": ${fileSizeKB}
  306.     }
  307.     </action>`;
  308.       } else {
  309.         messageContent = `<action>
  310.     {
  311.       "type": "file_upload",
  312.       "name": "${fileName}",
  313.       "content": ${JSON.stringify(fileContent)},
  314.       "size_kb": ${fileSizeKB}
  315.     }
  316.     </action>`;
  317.       }
  318.      
  319.       // Send the full content to the AI (not visible to the user)
  320.       sendMessage(messageContent, true);
  321.      
  322.       // Display only the file name and size to the user
  323.       const userVisibleMessage = `Uploaded file: ${fileName} (${fileSizeKB} KB)`;
  324.       appendMessage('user', userVisibleMessage);
  325.     }
  326.  
  327.     async function sendMessage(overrideMessage = null, isFileUpload = false) {
  328.       const message = overrideMessage || userInput.value.trim();
  329.       if (message === '') return;
  330.  
  331.       if (!isFileUpload) {
  332.         appendMessage('user', message);
  333.       }
  334.       userInput.value = '';
  335.       loadingIndicator.style.display = 'block';
  336.       cancelBtn.style.display = 'inline-block';
  337.       errorMessage.textContent = '';
  338.  
  339.       isRequestCancelled = false;
  340.       startTimer();
  341.  
  342.       while (!isRequestCancelled) {
  343.         try {
  344.           const controller = new AbortController();
  345.           const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout
  346.  
  347.           const response = await fetch('/api/chat', {
  348.             method: 'POST',
  349.             headers: {
  350.               'Content-Type': 'application/json',
  351.             },
  352.             body: JSON.stringify({ message: message, origin: 'https://claude.ai' }),
  353.             signal: controller.signal
  354.           });
  355.  
  356.           clearTimeout(timeoutId);
  357.  
  358.           if (response.ok) {
  359.             const data = await response.json();
  360.             appendMessage('ai', data.response);
  361.             break; // Exit the loop if we get a successful response
  362.           } else {
  363.             throw new Error('API response was not ok');
  364.           }
  365.         } catch (error) {
  366.           // Silently ignore errors and continue the loop
  367.           await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for 1 second before retrying
  368.         }
  369.       }
  370.  
  371.       loadingIndicator.style.display = 'none';
  372.       cancelBtn.style.display = 'none';
  373.       stopTimer();
  374.     }
  375.  
  376.     function appendMessage(sender, content) {
  377.       const messageDiv = document.createElement('div');
  378.       messageDiv.className = `message ${sender}-message`;
  379.      
  380.       // Parse content for code blocks
  381.       const parsedContent = parseCodeBlocks(content);
  382.       messageDiv.innerHTML = parsedContent;
  383.  
  384.       chatWindow.appendChild(messageDiv);
  385.       chatWindow.scrollTop = chatWindow.scrollHeight;
  386.  
  387.       // Initialize CodeMirror for code blocks
  388.       messageDiv.querySelectorAll('pre code').forEach((block) => {
  389.         const mode = block.className.replace('language-', '');
  390.         CodeMirror(function(elt) {
  391.           block.parentNode.replaceChild(elt, block);
  392.         }, {
  393.           value: block.textContent,
  394.           mode: mode,
  395.           lineNumbers: true,
  396.           readOnly: true,
  397.           theme: 'default'
  398.         });
  399.       });
  400.  
  401.       // Add message to current chat history
  402.       if (!chatHistories[currentChatId]) {
  403.         chatHistories[currentChatId] = [];
  404.       }
  405.       chatHistories[currentChatId].push({ sender, content });
  406.     }
  407.  
  408.     function parseCodeBlocks(content) {
  409.       const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
  410.       return content.replace(codeBlockRegex, (match, language, code) => {
  411.         return `<pre><code class="language-${language || 'plaintext'}">${escapeHtml(code.trim())}</code></pre>`;
  412.       });
  413.     }
  414.  
  415.     function escapeHtml(unsafe) {
  416.       return unsafe
  417.         .replace(/&/g, "&amp;")
  418.         .replace(/</g, "&lt;")
  419.         .replace(/>/g, "&gt;")
  420.         .replace(/"/g, "&quot;")
  421.         .replace(/'/g, "&#039;");
  422.     }
  423.  
  424.     function newChat() {
  425.       // Save current chat to history if it's not empty
  426.       if (chatHistories[currentChatId] && chatHistories[currentChatId].length > 0) {
  427.         const chatPreview = chatHistories[currentChatId][0].content.substring(0, 30) + '...';
  428.         addRecentChat(currentChatId, chatPreview);
  429.       }
  430.  
  431.       // Clear current chat window
  432.       chatWindow.innerHTML = '<div class="message ai-message"><p>Hello! How can I assist you today?</p></div>';
  433.       currentChatId = Date.now();
  434.       userInput.value = '';
  435.       errorMessage.textContent = '';
  436.     }
  437.  
  438.     function addRecentChat(id, preview) {
  439.       const li = document.createElement('li');
  440.       li.innerHTML = `<a onclick="loadChat(${id})">${preview}</a>`;
  441.       recentChats.insertBefore(li, recentChats.firstChild);
  442.  
  443.       // Limit to 5 recent chats
  444.       if (recentChats.children.length > 5) {
  445.         recentChats.removeChild(recentChats.lastChild);
  446.       }
  447.     }
  448.  
  449.     function loadChat(chatId) {
  450.       if (chatHistories[chatId]) {
  451.         chatWindow.innerHTML = ''; // Clear current chat window
  452.         chatHistories[chatId].forEach(message => {
  453.           appendMessage(message.sender, message.content);
  454.         });
  455.         chatWindow.scrollTop = chatWindow.scrollHeight;
  456.         currentChatId = chatId;
  457.       } else {
  458.         chatWindow.innerHTML = '<div class="message ai-message"><p>This chat history is not available.</p></div>';
  459.       }
  460.       userInput.value = '';
  461.       errorMessage.textContent = '';
  462.     }
  463.  
  464.     userInput.addEventListener('keydown', function(event) {
  465.       if (event.key === 'Enter' && !event.shiftKey) {
  466.         event.preventDefault();
  467.         sendMessage();
  468.       }
  469.     });
  470.  
  471.     userInput.addEventListener('input', function() {
  472.       this.style.height = 'auto';
  473.       this.style.height = this.scrollHeight + 'px';
  474.     });
  475.  
  476.     // Function to handle right-click on chatbot bubble
  477.     function handleChatbotBubbleRightClick(event, messageDiv) {
  478.       event.preventDefault();
  479.  
  480.       const codeBlock = messageDiv.querySelector('pre code');
  481.       if (codeBlock) {
  482.         // Code window exists, show "Copy Only This Code" option
  483.         showFloatingMenu(event.clientX, event.clientY, [
  484.           { label: 'Copy Only This Code', action: () => copyCode(codeBlock) }
  485.         ]);
  486.       } else {
  487.         // No code window, show "Copy This Reply" option
  488.         showRoundedMenu(event.clientX, event.clientY, [
  489.           { label: 'Copy This Reply', action: () => copyText(messageDiv.textContent) }
  490.         ]);
  491.       }
  492.     }
  493.  
  494.     // Function to handle right-click on user bubble
  495.     function handleUserBubbleRightClick(event, messageDiv) {
  496.       event.preventDefault();
  497.  
  498.       showRoundedMenu(event.clientX, event.clientY, [
  499.         { label: 'Edit', action: () => editMessage(messageDiv) }
  500.       ]);
  501.     }
  502.  
  503.     // Function to show floating menu
  504.     function showFloatingMenu(x, y, options) {
  505.       const menu = document.createElement('div');
  506.       menu.className = 'floating-menu';
  507.       menu.style.left = x + 'px';
  508.       menu.style.top = y + 'px';
  509.  
  510.       options.forEach(option => {
  511.         const menuItem = document.createElement('div');
  512.         menuItem.className = 'menu-item';
  513.         menuItem.textContent = option.label;
  514.         menuItem.addEventListener('click', option.action);
  515.         menu.appendChild(menuItem);
  516.       });
  517.  
  518.       document.body.appendChild(menu);
  519.  
  520.       // Close the menu when clicking outside
  521.       document.addEventListener('click', closeFloatingMenu);
  522.     }
  523.  
  524.     // Function to close floating menu
  525.     function closeFloatingMenu() {
  526.       const menu = document.querySelector('.floating-menu');
  527.       if (menu) {
  528.         menu.remove();
  529.         document.removeEventListener('click', closeFloatingMenu);
  530.       }
  531.     }
  532.  
  533.     // Function to show rounded menu
  534.     function showRoundedMenu(x, y, options) {
  535.       const menu = document.createElement('div');
  536.       menu.className = 'rounded-menu';
  537.       menu.style.left = x + 'px';
  538.       menu.style.top = y + 'px';
  539.  
  540.       options.forEach(option => {
  541.         const menuItem = document.createElement('div');
  542.         menuItem.className = 'menu-item';
  543.         menuItem.textContent = option.label;
  544.         menuItem.addEventListener('click', option.action);
  545.         menu.appendChild(menuItem);
  546.       });
  547.  
  548.       document.body.appendChild(menu);
  549.  
  550.       // Close the menu when clicking outside
  551.       document.addEventListener('click', closeRoundedMenu);
  552.     }
  553.  
  554.     // Function to close rounded menu
  555.     function closeRoundedMenu() {
  556.       const menu = document.querySelector('.rounded-menu');
  557.       if (menu) {
  558.         menu.remove();
  559.         document.removeEventListener('click', closeRoundedMenu);
  560.       }
  561.     }
  562.  
  563.     // Function to copy code
  564.     function copyCode(codeBlock) {
  565.       const textarea = document.createElement('textarea');
  566.       textarea.value = codeBlock.textContent;
  567.       document.body.appendChild(textarea);
  568.       textarea.select();
  569.       document.execCommand('copy');
  570.       document.body.removeChild(textarea);
  571.     }
  572.  
  573.     // Function to copy text
  574.     function copyText(text) {
  575.       const textarea = document.createElement('textarea');
  576.       textarea.value = text;
  577.       document.body.appendChild(textarea);
  578.       textarea.select();
  579.       document.execCommand('copy');
  580.       document.body.removeChild(textarea);
  581.     }
  582.  
  583.     // Function to edit message
  584.     function editMessage(messageDiv) {
  585.       const messageContent = messageDiv.textContent;
  586.       userInput.value = messageContent;
  587.  
  588.       // Delete all the text bubbles under the selected bubble
  589.       let nextSibling = messageDiv.nextSibling;
  590.       while (nextSibling) {
  591.         const nextMessageDiv = nextSibling;
  592.         nextSibling = nextSibling.nextSibling;
  593.         chatWindow.removeChild(nextMessageDiv);
  594.       }
  595.  
  596.       // Delete the selected text bubble
  597.       chatWindow.removeChild(messageDiv);
  598.     }
  599.  
  600.     // Add event listeners for right-click on chatbot and user bubbles
  601.     chatWindow.addEventListener('contextmenu', event => {
  602.       const messageDiv = event.target.closest('.message');
  603.       if (messageDiv && messageDiv.classList.contains('ai-message')) {
  604.         handleChatbotBubbleRightClick(event, messageDiv);
  605.       } else if (messageDiv && messageDiv.classList.contains('user-message')) {
  606.         handleUserBubbleRightClick(event, messageDiv);
  607.       }
  608.     });
  609.   </script>
  610. </body>
  611. </html>
  612.  
  613.  
  614.   </script>
  615. </body>
  616. </html>
Add Comment
Please, Sign In to add comment