├── scripts ├── requirements.txt └── CreateNewPack.py ├── src ├── assets │ ├── Logo │ │ ├── logo.png │ │ ├── logo48.png │ │ └── logoHD.png │ ├── Usage │ │ ├── Start.GIF │ │ ├── Stop.GIF │ │ ├── Plugin.GIF │ │ ├── popup_1.png │ │ ├── popup_2.png │ │ ├── Connecting.GIF │ │ └── CountDown.GIF │ └── webfonts │ │ ├── fa-solid-900.ttf │ │ ├── fa-brands-400.ttf │ │ ├── fa-regular-400.ttf │ │ ├── fa-solid-900.woff2 │ │ ├── fa-brands-400.woff2 │ │ ├── fa-regular-400.woff2 │ │ ├── fa-v4compatibility.ttf │ │ └── fa-v4compatibility.woff2 ├── config.json ├── manifest.json ├── background.js ├── Privacy Policy.html ├── popup.js ├── popup.html ├── Terms of Service.html ├── injected-popup.js ├── content.js └── crypto-js.min.js ├── .gitignore ├── ReleaseNotes.md ├── package.json ├── IMPROVEMENTS.md ├── LICENSE_NOTICE.md ├── CONTRIBUTING.md ├── README.md └── LICENSE-APACHE.txt /scripts/requirements.txt: -------------------------------------------------------------------------------- 1 | jsmin 2 | logging 3 | zipfile 4 | -------------------------------------------------------------------------------- /src/assets/Logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/Logo/logo.png -------------------------------------------------------------------------------- /src/assets/Logo/logo48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/Logo/logo48.png -------------------------------------------------------------------------------- /src/assets/Logo/logoHD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/Logo/logoHD.png -------------------------------------------------------------------------------- /src/assets/Usage/Start.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/Usage/Start.GIF -------------------------------------------------------------------------------- /src/assets/Usage/Stop.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/Usage/Stop.GIF -------------------------------------------------------------------------------- /src/assets/Usage/Plugin.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/Usage/Plugin.GIF -------------------------------------------------------------------------------- /src/assets/Usage/popup_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/Usage/popup_1.png -------------------------------------------------------------------------------- /src/assets/Usage/popup_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/Usage/popup_2.png -------------------------------------------------------------------------------- /src/assets/Usage/Connecting.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/Usage/Connecting.GIF -------------------------------------------------------------------------------- /src/assets/Usage/CountDown.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/Usage/CountDown.GIF -------------------------------------------------------------------------------- /src/assets/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /src/assets/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /src/assets/webfonts/fa-regular-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/webfonts/fa-regular-400.ttf -------------------------------------------------------------------------------- /src/assets/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /src/assets/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /src/assets/webfonts/fa-regular-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/webfonts/fa-regular-400.woff2 -------------------------------------------------------------------------------- /src/assets/webfonts/fa-v4compatibility.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/webfonts/fa-v4compatibility.ttf -------------------------------------------------------------------------------- /src/assets/webfonts/fa-v4compatibility.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/improveTheWorld/ChatGPT-Bridge/HEAD/src/assets/webfonts/fa-v4compatibility.woff2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # .gitignore 2 | 3 | # Ignore everything in the dist folder 4 | /dist/* 5 | 6 | # But do not ignore the release notes file 7 | !/dist/RELEASE_NOTES.md 8 | .DS_Store 9 | dist.crx 10 | dist.pem 11 | -------------------------------------------------------------------------------- /ReleaseNotes.md: -------------------------------------------------------------------------------- 1 | # V1.2.0, What's new? 2 | 3 | * Add authentification token mechanism to use ChatGPT-Executor-1.2.0, 4 | * Support the newest ChatGPT page's html ( ChatGPT May 24 Version), 5 | * Add a donate link into popup.html. -------------------------------------------------------------------------------- /src/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "pollingFrequency": 1000, 3 | "messageCompletionTime": 3000, 4 | "streamingMode": false, 5 | "communicationPort": 8181, 6 | "reconnectInterval": 1000, 7 | "feedbackDelay": 200, 8 | "authenticationNeeded" : false 9 | } 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ChatGPT-Bridge", 3 | "version": "1.3.0", 4 | "description": "A web browser plugin that offers API-like access to ChatGPT, working alongside ChatGPT-Executor.", 5 | "main": "index.js", 6 | "scripts": {}, 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/improveTheWorld/ChatGPT-Bridge.git" 10 | }, 11 | "author": "Tec-Net", 12 | "license": "Apache-2.0" 13 | } 14 | -------------------------------------------------------------------------------- /IMPROVEMENTS.md: -------------------------------------------------------------------------------- 1 | * Add hide button for countdown window 2 | * Add "+1 in" list window for all the future message credit 3 | * Make the plugin capable of continuing the communication when allowed messages are credit again ( plan future tasks) 4 | * configure the start value of the countDown 5 | * Count down the messages credit when a message is updated and resent 6 | * when start a new chat session , it will be more optimized ( in the term of the number of message used) to prompt the first task , and to append it to the first Prompt 7 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "name": "ChatGPT-Bridge", 4 | "version": "1.0.2", 5 | "permissions": ["activeTab", "storage", "tabs"], 6 | "action": { 7 | "default_popup": "popup.html", 8 | "default_icon": { 9 | "48": "/assets/Logo/logo48.png" 10 | } 11 | }, 12 | "background": { 13 | "service_worker": "background.js" 14 | }, 15 | "content_scripts": [ 16 | { 17 | "matches": ["https://chatgpt.com/*"], 18 | "js": ["crypto-js.min.js","content.js"], 19 | "run_at": "document_end" 20 | } 21 | ], 22 | "host_permissions": ["https://chatgpt.com/*"], 23 | "icons": { 24 | "48": "/assets/Logo/logo48.png" 25 | }, 26 | "web_accessible_resources": [ 27 | { 28 | "resources": [ 29 | "config.json", 30 | "injected-popup.js", 31 | "firstPrompt.txt", 32 | "Terms of Service.html", 33 | "Privacy Policy.html", 34 | "assets/css/all.min.css", 35 | "assets/webfonts/*" 36 | ], 37 | "matches": [""] 38 | } 39 | ] 40 | } -------------------------------------------------------------------------------- /src/background.js: -------------------------------------------------------------------------------- 1 | // # File: background.js 2 | // # Software: ChatGPT-Bridge 3 | // # Purpose: Provide third-party software with the capability to utilize ChatGPT. 4 | // # 5 | // # Copyright © 2023 Tec-Net 6 | // # 7 | // # Dual License Notice 8 | // # 9 | // # For Free Software Projects: 10 | // # This software is licensed under the Apache License, Version 2.0; 11 | // # you may not use this file except in compliance with the License. 12 | // # You may obtain a copy of the License at 13 | // # 14 | // # http://www.apache.org/licenses/LICENSE-2.0 15 | // # 16 | // # For Non-Free Software Projects: 17 | // # This software requires a commercial license. Please contact the author at 18 | // # tecnet.paris@gmail.com to discuss licensing terms and pricing. 19 | // # 20 | // # Unless required by applicable law or agreed to in writing, software 21 | // # distributed under the License is distributed on an "AS IS" BASIS, 22 | // # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | // # See the License for the specific language governing permissions and 24 | // # limitations under the License. 25 | 26 | chrome.runtime.onInstalled.addListener(() => { 27 | console.log('Chat Bridge extension installed'); 28 | }); 29 | -------------------------------------------------------------------------------- /LICENSE_NOTICE.md: -------------------------------------------------------------------------------- 1 | # Dual License Notice 2 | 3 | This software is licensed under two separate licenses: a permissive open-source license for free software projects, and a commercial license for non-free software projects. By using this software, you agree to comply with the terms of the appropriate license. 4 | 5 | ## For Free Software Projects 6 | 7 | If you are using this software in a free software project, you may use it under the terms of the [Apache License, Version 2.0](LICENSE-APACHE.txt). This license allows for free use, modification, and distribution, as long as you include the copyright notice, license text, and any modifications made to the software are clearly marked. 8 | 9 | ## For Non-Free Software Projects 10 | 11 | If you are using this software in a non-free software project, you are required to obtain a commercial license. Please contact the author at bilelgatri@gmail.com to discuss licensing terms and pricing. 12 | 13 | By using this software in a non-free software project without obtaining a commercial license, you agree that you are in violation of the terms of this notice and may be subject to legal action. 14 | 15 | ## Acknowledgment and Link for Both Commercial and Non-Commercial Use 16 | 17 | Regardless of whether your use is commercial or non-commercial, when using the compiled version of this software in a third-party project, we kindly ask that you acknowledge the author and provide a link to the software GitHub repository. 18 | 19 | Remember, this dual-license notice is provided as a reference and may not cover all legal aspects. Consult with a legal professional to ensure your licensing choices meet your specific requirements and expectations. 20 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | Thank you for your interest in contributing to ChatGPT-Bridge! We appreciate your effort and value your contributions. This document provides guidelines to help make the contribution process smooth and effective for everyone involved. 4 | 5 | ## Getting Started 6 | 7 | 1. **Fork the repository**: Start by forking the repository to your own GitHub account. This allows you to make changes to the project without affecting the original repository. 8 | 9 | 2. **Create a branch**: Create a new branch with a descriptive name based on the feature or bugfix you plan to work on. For example, `fix-issue-123` or `add-new-feature`. 10 | 11 | 3. **Clone the repository**: Clone the forked repository to your local machine and set the upstream remote to the original repository. 12 | 13 | >git clone https://github.com/improveTheWorld/ChatGPT-Bridge.git 14 | 15 | >cd ChatGPT-Bridge 16 | 17 | >git remote add upstream https://github.com/improveTheWorld/ChatGPT-Bridge.git 18 | 19 | 20 | 21 | ## Contributing Code 22 | 23 | 1. **Sync your fork**: Before starting your work, ensure your fork is up-to-date with the original repository. 24 | 25 | git fetch upstream 26 | git merge upstream/main 27 | 28 | 29 | 2. **Write clean and well-documented code**: While working on your changes, make sure to follow the project's coding style and write well-documented code. 30 | 31 | 3. **Test your changes**: Test your changes thoroughly to ensure that you do not introduce new bugs. 32 | 33 | 4. **Commit your changes**: Break your work into small, logical commits with descriptive commit messages. This makes it easier for maintainers to review your changes. 34 | 35 | 5. **Push your changes**: Push your changes to your fork on GitHub. 36 | 37 | git push origin 38 | 39 | 40 | ## Submitting a Pull Request 41 | 42 | 1. **Create a Pull Request**: Go to the original repository on GitHub, and click the "New Pull Request" button. Choose the branch you worked on and submit the Pull Request. 43 | 44 | 2. **Describe your changes**: In the Pull Request description, provide a clear and concise explanation of the changes you made, referencing any related issues or discussions. 45 | 46 | 3. **Wait for a review**: The maintainers will review your Pull Request and may request changes or ask questions. Please be patient and address any feedback provided. 47 | 48 | 4. **Make any requested changes**: If the maintainers request changes, make the necessary updates and push the changes to your branch. 49 | 50 | 5. **Celebrate**: Once your Pull Request is merged, you've successfully contributed to the project! Thank you for your efforts! 51 | 52 | ## Reporting Issues 53 | 54 | If you find a bug or have a suggestion, please [open a new issue](https://github.com/improveTheWorld/ChatGPT-Bridge/issues/new) in the repository. When reporting a bug, provide as much information as possible, including steps to reproduce the problem, your operating system, and any relevant error messages. 55 | 56 | ## Additional Resources 57 | 58 | - [GitHub Documentation](https://docs.github.com/en) 59 | - [Git Documentation](https://git-scm.com/doc) 60 | 61 | Thank you for contributing to [Your Project Name]! 62 | Remember to replace [Your Project Name], , , and with the appropriate information for your project. -------------------------------------------------------------------------------- /src/Privacy Policy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ChatGPT Bridge Plugin - Privacy Policy 7 | 8 | 60 | 61 | 62 |
63 |

ChatGPT Bridge Plugin - Privacy Policy

64 |

1. Introduction

65 |

66 | This Privacy Policy explains how we collect, use, and protect your personal information when you use the ChatGPT Bridge Plugin. By using the plugin, you agree to the terms of this Privacy Policy. If you do not agree with the terms, please do not use the plugin. 67 |

68 | 69 |

2. Information We Collect

70 |

71 | We do not collect any personally identifiable information when you use the ChatGPT Bridge Plugin. The plugin communicates with a web server to execute commands locally on your computer, but no personal information is transmitted or stored by the plugin or the web server. 72 |

73 | 74 |

3. How We Use Information

75 |

76 | As no personal information is collected, we do not use any information for any purpose. 77 |

78 | 79 |

4. Information Security

80 |

81 | We are committed to protecting the privacy and security of your information. While no personal information is collected, we still employ industry-standard security measures to ensure the confidentiality and integrity of the plugin's communication with the web server. 82 |

83 | 84 |

5. Third-Party Services

85 |

86 | The ChatGPT Bridge Plugin may utilize third-party services for its operation. However, we do not share any personal information with these services. Please refer to the privacy policies of 87 | 88 | any third-party services used by the plugin for more information on their data collection and usage practices. 89 | 90 |

6. Changes to This Privacy Policy

91 |

92 | We may update this Privacy Policy from time to time to reflect changes in our practices, technologies, legal requirements, or other factors. When we make updates, we will change the "last updated" date at the top of this policy. We encourage you to review this Privacy Policy periodically to stay informed about our privacy practices and how we are protecting your information. 93 |

94 | 95 |

7. Contact Information

96 |

97 | If you have any questions, concerns, or suggestions regarding this Privacy Policy or the ChatGPT Bridge Plugin, please contact the plugin's developer through the contact channels provided on the plugin's webpage or in the plugin's documentation. 98 |

99 |
100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/popup.js: -------------------------------------------------------------------------------- 1 | // # File: popup.js 2 | // # Software: ChatGPT Bridge 3 | // # Purpose: Provide third-party software with the capability to utilize ChatGPT. 4 | // # 5 | // # Copyright 2023 B.GATRI 6 | // # 7 | // # Dual License Notice 8 | // # 9 | // # For Free Software Projects: 10 | // # This software is licensed under the Apache License, Version 2.0 (the "License"); 11 | // # you may not use this file except in compliance with the License. 12 | // # You may obtain a copy of the License at 13 | // # 14 | // # http://www.apache.org/licenses/LICENSE-2.0 15 | // # 16 | // # For Non-Free Software Projects: 17 | // # This software requires a commercial license. Please contact the author at 18 | // # bilelgatri@gmail.com to discuss licensing terms and pricing. 19 | // # 20 | // # Unless required by applicable law or agreed to in writing, software 21 | // # distributed under the License is distributed on an "AS IS" BASIS, 22 | // # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | // # See the License for the specific language governing permissions and 24 | // # limitations under the License. 25 | (async () => { 26 | const startStopButton = document.querySelector('#startButton'); 27 | //const logElement = document.querySelector('#log'); 28 | let monitoring = false; 29 | let connectionStatus = 'connecting'; 30 | 31 | function logMessage(message) { 32 | //logElement.textContent += message + '\n'; 33 | console.log('LOG:' + message) 34 | } 35 | 36 | 37 | function updateButtonState() { 38 | logMessage('Status : Connection ='+connectionStatus+', Monitoring ='+monitoring); 39 | if (connectionStatus === 'connected') { 40 | if (monitoring) { 41 | startStopButton.innerHTML = ' Stop'; 42 | } else { 43 | startStopButton.innerHTML = ' Start'; 44 | } 45 | startStopButton.disabled = false; 46 | } else { 47 | startStopButton.innerHTML = ' Connecting...'; 48 | startStopButton.disabled = true; 49 | } 50 | } 51 | 52 | ////////////////////////////////////// Main /////////////////////////////////// 53 | chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { 54 | if (request.connectionStatus) { 55 | connectionStatus = request.connectionStatus; 56 | updateButtonState(); 57 | sendResponse('StartStopButton Updated'); 58 | } 59 | }); 60 | 61 | // document.addEventListener('DOMContentLoaded', () => { 62 | startStopButton.addEventListener('click', () => { 63 | monitoring = !monitoring; 64 | updateButtonState(); 65 | if (monitoring) { 66 | chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { 67 | chrome.tabs.sendMessage(tabs[0].id, { start: true }, (response) => { 68 | if (chrome.runtime.lastError) { 69 | logMessage('Error: ' + chrome.runtime.lastError.message); 70 | } else { 71 | logMessage(response.message); 72 | } 73 | }); 74 | }); 75 | } else { 76 | chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { 77 | chrome.tabs.sendMessage(tabs[0].id, { stop: true }, (response) => { 78 | if (chrome.runtime.lastError) { 79 | logMessage('Error: ' + chrome.runtime.lastError.message); 80 | } else { 81 | logMessage(response.message); 82 | } 83 | }); 84 | }); 85 | } 86 | }); 87 | // }); 88 | 89 | 90 | // Add these lines to the existing popup.js to handle automatic start when the chat page is loaded 91 | chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { 92 | if (tabs[0].url.startsWith('https://chat.openai.com/*')) { 93 | startStopButton.click(); 94 | } 95 | }); 96 | 97 | chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { 98 | if (changeInfo.status === 'complete' && tab.url.startsWith('https://chat.openai.com/*')) { 99 | startStopButton.click(); 100 | } 101 | }); 102 | 103 | // // Load font-awesome icons 104 | const link = document.createElement('link'); 105 | link.rel = 'stylesheet'; 106 | link.href = chrome.runtime.getURL('./assets/css/all.min.css'); 107 | document.head.appendChild(link); 108 | })(); 109 | 110 | -------------------------------------------------------------------------------- /src/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ChatGPT Bridge Plugin 7 | 101 | 102 | 103 |
104 |
105 |

ChatGPT-Bridge

106 |

Version 1.1.0 - Released 11/05/2023

107 |
108 |
109 |

This Plugin allows users to access and execute Windows commands through ChatGPT. It seamlessly communicates with a third party software ChatGPT-Executor that runs commands locally and provides real-time output, enabling ChatGPT to perform tasks for you. If not yet installed : 110 |

111 | 112 |

113 | Download ChatGPT-Executor-1.2.0 Now

114 |

115 | Experience a new level of convenience and productivity with ChatGPT. Bridge the gap between AI and your computer to get more done, faster than ever before. 116 |

117 | 118 | Check for Updates 119 | 120 |

Support our mission to transform the world by empowering us with your contributions. Every donation helps us to continuously innovate and improve.

121 |

Contribute Now

122 | 123 |

124 | Need assistance or have a suggestion? Get in touch with the plugin developer by sending a direct message to tecnet.paris@gmail.com. 125 |

126 |
127 | 130 |
131 | 132 | -------------------------------------------------------------------------------- /scripts/CreateNewPack.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | import shutil 4 | import tempfile 5 | import zipfile 6 | import datetime 7 | import logging 8 | import jsmin 9 | # Set up logging 10 | logging.basicConfig(level=logging.INFO) 11 | logger = logging.getLogger(__name__) 12 | 13 | def read_config(config_path): 14 | """Read version and name from config.json""" 15 | try: 16 | with open(config_path, 'r') as f: 17 | data = json.load(f) 18 | return data.get('version'), data.get('name') 19 | except FileNotFoundError: 20 | logger.error(f"{config_path} file not found") 21 | return None, None 22 | except json.JSONDecodeError: 23 | logger.error("Invalid JSON in config file") 24 | return None, None 25 | 26 | def create_temp_dir(): 27 | """Create a temporary directory""" 28 | return tempfile.mkdtemp() 29 | 30 | def copy_source_files(source_dir, dest_dir): 31 | """Copy source files to destination directory""" 32 | try: 33 | shutil.copytree(source_dir, dest_dir) 34 | logger.info(f"Copied files from {source_dir} to {dest_dir}") 35 | except FileExistsError: 36 | logger.warning(f"Destination {dest_dir} already exists, overwriting...") 37 | shutil.rmtree(dest_dir) 38 | shutil.copytree(source_dir, dest_dir) 39 | except Exception as e: 40 | logger.error(f"Error copying files: {e}") 41 | raise 42 | 43 | def update_manifest(manifest_path, version): 44 | """Update version in manifest.json""" 45 | try: 46 | with open(manifest_path, 'r+') as f: 47 | data = json.load(f) 48 | data['version'] = version 49 | f.seek(0) 50 | json.dump(data, f, indent=2) 51 | f.truncate() 52 | logger.info(f"Updated manifest at {manifest_path}") 53 | except Exception as e: 54 | logger.error(f"Error updating manifest: {e}") 55 | raise 56 | 57 | def update_popup_html(popup_path, version, release_date): 58 | """Update version and release date in popup.html""" 59 | try: 60 | with open(popup_path, 'r+') as f: 61 | content = f.read() 62 | # Replace the version and release date 63 | updated_content = content.replace( 64 | '

Version .* - Released .*

', 65 | f'

Version {version} - Released {release_date}

' 66 | ) 67 | f.seek(0) 68 | f.write(updated_content) 69 | f.truncate() 70 | logger.info(f"Updated popup.html at {popup_path}") 71 | except Exception as e: 72 | logger.error(f"Error updating popup.html: {e}") 73 | raise 74 | 75 | def minify_javascript(js_path): 76 | """Minify JavaScript files using jsmin""" 77 | try: 78 | 79 | with open(js_path, 'r+') as f: 80 | content = f.read() 81 | minified = jsmin.jsmin(content) 82 | f.seek(0) 83 | f.write(minified) 84 | f.truncate() 85 | logger.info(f"Minified {js_path}") 86 | except Exception as e: 87 | logger.error(f"Error minifying {js_path}: {e}") 88 | raise 89 | 90 | def create_zip_archive(source_dir, zip_path): 91 | """Create a zip file from source directory""" 92 | try: 93 | with zipfile.ZipFile(zip_path, 'w') as zip_file: 94 | for root, dirs, files in os.walk(source_dir): 95 | for file in files: 96 | file_path = os.path.join(root, file) 97 | rel_path = os.path.relpath(file_path, source_dir) 98 | zip_file.write(file_path, rel_path) 99 | logger.info(f"Created zip file at {zip_path}") 100 | except Exception as e: 101 | logger.error(f"Error creating zip file: {e}") 102 | raise 103 | 104 | def extract_zip(zip_path, dest_dir): 105 | """Extract zip file to destination directory""" 106 | try: 107 | with zipfile.ZipFile(zip_path, 'r') as zip_file: 108 | zip_file.extractall(dest_dir) 109 | logger.info(f"Extracted zip to {dest_dir}") 110 | except Exception as e: 111 | logger.error(f"Error extracting zip: {e}") 112 | raise 113 | 114 | def main(): 115 | # Read config 116 | config_path = 'package.json' 117 | version, name = read_config(config_path) 118 | if not version or not name: 119 | logger.error("Failed to read version or name from config") 120 | return 121 | 122 | # Create temp dir 123 | temp_dir = create_temp_dir() 124 | logger.info(f"Created temp dir at {temp_dir}") 125 | 126 | # Copy source files 127 | source_dir = os.path.join(os.path.dirname(config_path), 'src') 128 | dest_dir = os.path.join(temp_dir, 'src') 129 | copy_source_files(source_dir, dest_dir) 130 | 131 | # Update manifest 132 | manifest_path = os.path.join(dest_dir, 'manifest.json') 133 | update_manifest(manifest_path, version) 134 | 135 | # Update popup.html 136 | popup_path = os.path.join(dest_dir, 'popup.html') 137 | release_date = datetime.datetime.now().strftime('%Y-%m-%d') 138 | update_popup_html(popup_path, version, release_date) 139 | 140 | # Minify JavaScript files 141 | for root, dirs, files in os.walk(dest_dir): 142 | for file in files: 143 | if file.endswith('.js'): 144 | js_path = os.path.join(root, file) 145 | minify_javascript(js_path) 146 | 147 | # Create zip file 148 | zip_name = f"{name}_{version}.zip" 149 | zip_path = os.path.join(os.path.dirname(config_path), 'dist', zip_name) 150 | os.makedirs(os.path.dirname(zip_path), exist_ok=True) 151 | create_zip_archive(dest_dir, zip_path) 152 | 153 | # Extract zip to dist 154 | extract_zip(zip_path, os.path.join(os.path.dirname(config_path), 'dist')) 155 | 156 | # Cleanup 157 | shutil.rmtree(temp_dir) 158 | logger.info("Cleaned up temporary directory") 159 | 160 | if __name__ == "__main__": 161 | main() 162 | -------------------------------------------------------------------------------- /src/Terms of Service.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ChatGPT Bridge Plugin - Terms of Service 7 | 45 | 46 | 47 |
48 |

ChatGPT Bridge Plugin - Terms of Service

49 | 50 |

1. Acceptance of Terms

51 |

52 | By using the ChatGPT Bridge Plugin, you agree to be bound by these Terms of Service. If you do not agree to these terms, you should not use the plugin. 53 |

54 | 55 | 56 | 57 | 58 |

2. Dual License Notice

59 |

60 | This software is licensed under two separate licenses: a permissive open-source license for free software projects, and a commercial license for non-free software projects. By using this software, you agree to comply with the terms of the appropriate license. 61 |

62 | 63 |

a) For Free Software Projects

64 |

65 | If you are using this software in a free software project, you may use it under the terms of the Apache License, Version 2.0. This license allows for free use, modification, and distribution, as long as you include the copyright notice, license text, and any modifications made to the software are clearly marked. 66 |

67 | 68 |

b) For Non-Free Software Projects

69 |

70 | If you are using this software in a non-free software project, you are required to obtain a commercial license. Please contact the author at tecnet.paris@gmail.com to discuss licensing terms and pricing. 71 |

72 |

73 | By using this software in a non-free software project without obtaining a commercial license, you agree that you are in violation of the terms of this notice and may be subject to legal action. 74 |

75 |

c) Acknowledgment and Link for Both Commercial and Non-Commercial Use

76 |

77 | Regardless of whether your use is commercial or non-commercial, when using the compiled version of this software in a third-party project, we kindly ask that you acknowledge the author and provide a link to the software GitHub repository. 78 |

79 | 80 | 81 | 82 | 83 | 84 |

2. Disclaimer of Warranty and Limitation of Liability

85 |

86 | The ChatGPT Bridge Plugin is provided "AS IS" without any warranty, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, or non-infringement. The plugin's developer, contributors, and any affiliated parties do not assume any responsibility or liability for any errors, omissions, or issues that may arise from the use of the plugin. 87 |

88 |

89 | In no event shall the plugin's developer, contributors, or any affiliated parties be liable for any damages, including but not limited to, direct, indirect, incidental, consequential, or special damages, arising out of or in connection with the use or performance of the ChatGPT Bridge Plugin, even if advised of the possibility of such damages. 90 |

91 | 92 |

3. Indemnification

93 |

94 | You agree to indemnify, defend, and hold harmless the plugin's developer, contributors, and any affiliated parties from and against any and all claims, liabilities, losses, damages, or expenses, including but not limited to attorney fees, arising out of or in connection with your use of the ChatGPT Bridge Plugin. 95 |

96 | 97 |

4. Modifications to Terms of Service

98 |

99 | The plugin's developer reserves the right to modify these Terms of Service at any time without prior notice. Your continued use of the ChatGPT Bridge Plugin constitutes your acceptance of the updated Terms of Service. 100 |

101 | 102 |

5. Governing Law

103 |

104 | These Terms of Service shall be governed by and construed in accordance with the laws of the jurisdiction in which the plugin's developer is located, without regard to its conflict of law provisions. Any disputes arising from or in connection with these Terms of Service shall be subject to the exclusive jurisdiction of the courts of the same jurisdiction. 105 |

106 | 107 |

6. Severability

108 |

109 | If any provision of these Terms of Service is found to be invalid or unenforceable by a court of competent jurisdiction, the remaining provisions shall remain in full force and effect, and the invalid or unenforceable provision shall be deemed superseded by a valid, enforceable provision that most closely matches the intent of the original provision. 110 |

111 | 112 |

7. Termination

113 |

114 | The plugin's developer reserves the right, in its sole discretion, to terminate your access to the ChatGPT Bridge Plugin at any time, without notice, for any reason, including but not limited to your violation of these Terms of Service. 115 |

116 | 117 |

9. Contact Information

118 |

119 | If you have any questions, concerns, or suggestions regarding these Terms of Service or the ChatGPT Bridge Plugin, please contact the plugin's developer through the contact channels provided on the plugin's webpage or in the plugin's documentation. 120 |

121 |
122 | 123 | -------------------------------------------------------------------------------- /src/injected-popup.js: -------------------------------------------------------------------------------- 1 | // # File: injected-popup.js 2 | // # Software: ChatGPT-Bridge 3 | // # Purpose: Provide third-party software with the capability to utilize ChatGPT. 4 | // # 5 | // # Copyright © 2023 Tec-Net 6 | // # 7 | // # Dual License Notice 8 | // # 9 | // # For Free Software Projects: 10 | // # This software is licensed under the Apache License, Version 2.0; 11 | // # you may not use this file except in compliance with the License. 12 | // # You may obtain a copy of the License at 13 | // # 14 | // # http://www.apache.org/licenses/LICENSE-2.0 15 | // # 16 | // # For Non-Free Software Projects: 17 | // # This software requires a commercial license. Please contact the author at 18 | // # tecnet.paris@gmail.com to discuss licensing terms and pricing. 19 | // # 20 | // # Unless required by applicable law or agreed to in writing, software 21 | // # distributed under the License is distributed on an "AS IS" BASIS, 22 | // # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | // # See the License for the specific language governing permissions and 24 | // # limitations under the License. 25 | 26 | 27 | 28 | (async () => { 29 | 30 | /* */ 37 | 38 | 39 | const startStopButton = document.querySelector('#startButton'); 40 | const topIcon = document.querySelector('#topIcon'); 41 | const countElemnet = document.querySelector('#countDown'); 42 | const timerCountDownElemnet = document.querySelector('#timerCountDown'); 43 | const timerCountDownMessageElemnet = document.querySelector('#countDownMessage'); 44 | 45 | let timerCountDownPollId; 46 | 47 | //const logElement = document.querySelector('#log'); 48 | let monitoring = false; 49 | let connectionStatus = 'connecting'; 50 | let timerCounDownNum = -1; 51 | 52 | 53 | function logMessage(message) { 54 | //logElement.textContent += message + '\n'; 55 | console.log('LOG:' + message); 56 | } 57 | 58 | function updateButtonState() { 59 | if (connectionStatus === 'connected') { 60 | topIcon.innerHTML = ' Bridge'; 61 | if (monitoring) { 62 | startStopButton.innerHTML = ' Stop'; 63 | } else { 64 | startStopButton.innerHTML = ' Start'; 65 | } 66 | //startStopButton.disabled = false; 67 | } else if (connectionStatus === 'connecting') { 68 | topIcon.innerHTML = ' Bridge'; 69 | startStopButton.innerHTML = ''; 70 | //startStopButton.disabled = true; 71 | } else if (connectionStatus === 'disconnected') { 72 | topIcon.innerHTML = ' Bridge'; 73 | startStopButton.innerHTML = ''; 74 | } 75 | } 76 | 77 | function onNewConnexionStatus(status) { 78 | if (status != connectionStatus) { 79 | connectionStatus = status; 80 | updateButtonState(); 81 | } 82 | } 83 | 84 | function emitEvent(name, detail = null) { 85 | const event = new CustomEvent(name, { detail }); 86 | window.dispatchEvent(event); 87 | } 88 | 89 | function formatTime(milliseconds) { 90 | const hours = Math.floor(milliseconds / 3600000); // 1 hour = 3600000 ms 91 | const minutes = Math.floor((milliseconds % 3600000) / 60000); // 1 minute = 60000 ms 92 | return `${hours}h:${minutes}min`; 93 | } 94 | 95 | function toggleCountdownContainer(visible) { 96 | const countdownContainer = document.getElementById('countdown-container'); 97 | const popupContainer = document.getElementById('popup-container'); 98 | 99 | 100 | if (visible) { 101 | countdownContainer.style.display = 'flex'; 102 | popupContainer.style.width = 215 + 'px'; 103 | } else { 104 | countdownContainer.style.display = 'none'; 105 | popupContainer.style.width = 140 + 'px'; // Set the new maxWidth value 106 | } 107 | } 108 | 109 | 110 | 111 | 112 | function updatetimerCountDownElement() { 113 | if (timerCounDownNum > 0) { 114 | 115 | toggleCountdownContainer(true); 116 | timerCountDownElemnet.innerText = formatTime(timerCounDownNum); 117 | timerCountDownMessageElemnet.innerText = '+1 in '; 118 | 119 | } 120 | else { 121 | toggleCountdownContainer(false); 122 | //timerCountDownElemnet.innerText = ''; 123 | //timerCountDownMessageElemnet.innerText = ''; 124 | } 125 | 126 | } 127 | 128 | ////////////////////////////////////// Main /////////////////////////////////// 129 | 130 | window.addEventListener('connecting', () => { 131 | onNewConnexionStatus('connecting'); 132 | }); 133 | window.addEventListener('connected', () => { 134 | onNewConnexionStatus('connected'); 135 | }); 136 | window.addEventListener('disconnected', () => { 137 | onNewConnexionStatus('disconnected'); 138 | }); 139 | 140 | window.addEventListener('newCountDown', (event) => { 141 | 142 | countElemnet.innerText = event.detail.countDown; 143 | timerCounDownNum = event.detail.timerCounDown; 144 | updatetimerCountDownElement(); 145 | if (timerCountDownPollId) { 146 | clearInterval(timerCountDownPollId); 147 | 148 | } 149 | 150 | timerCountDownPollId = setInterval(() => { 151 | timerCounDownNum -= 60000; 152 | updatetimerCountDownElement(); 153 | 154 | }, 60000); 155 | 156 | }); 157 | 158 | 159 | 160 | 161 | 162 | startStopButton.addEventListener('click', () => { 163 | monitoring = !monitoring; 164 | if (connectionStatus === 'connected') { 165 | if (monitoring) { 166 | emitEvent('startSendingFeedback'); 167 | } 168 | else { 169 | emitEvent('stopSendingFeedback'); 170 | } 171 | } 172 | else { 173 | if (connectionStatus === 'connecting') { 174 | connectionStatus = 'disconnected'; 175 | emitEvent('disconnect'); 176 | } 177 | else { //disconnected 178 | connectionStatus = 'connecting'; 179 | emitEvent('connect') 180 | } 181 | } 182 | 183 | updateButtonState(); 184 | }); 185 | 186 | 187 | // Initialize button state 188 | updateButtonState(); 189 | 190 | ////////////////////////////////////////////// Drag and drop popup management ////////////////////// 191 | var popupContainer = document.getElementById('popup-container'); 192 | popupContainer.addEventListener('mousedown', dragStart); 193 | 194 | // Prevent the mousedown event from bubbling when clicking on the button 195 | document.getElementById('startButton').addEventListener('mousedown', function (e) { 196 | e.stopPropagation(); 197 | }, false); 198 | 199 | // The rest of the code remains the same 200 | 201 | 202 | 203 | // var popupContainer = document.getElementById('popup-container'); 204 | // popupContainer.addEventListener('mousedown', dragStart); 205 | 206 | var offsetX, offsetY; 207 | 208 | function dragStart(e) { 209 | e.preventDefault(); 210 | offsetX = e.clientX - popupContainer.offsetLeft; 211 | offsetY = e.clientY - popupContainer.offsetTop; 212 | document.addEventListener('mousemove', drag); 213 | document.addEventListener('mouseup', dragEnd); 214 | } 215 | 216 | function drag(e) { 217 | e.preventDefault(); 218 | popupContainer.style.left = (e.clientX - offsetX) + 'px'; 219 | popupContainer.style.top = (e.clientY - offsetY) + 'px'; 220 | } 221 | 222 | function dragEnd(e) { 223 | e.preventDefault(); 224 | document.removeEventListener('mousemove', drag); 225 | document.removeEventListener('mouseup', dragEnd); 226 | } 227 | 228 | // injected-popup.js ready 229 | 230 | const popupReadyEvent = new CustomEvent('popupReady'); 231 | document.dispatchEvent(popupReadyEvent); 232 | 233 | })(); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![ChatGPT-Bridge Logo](./src/assets/Logo/logo.png) **ChatGPT-Bridge** 2 | 3 | # Tired of waiting for access to the GPT-4 API? Frustrated by the fees charged for using the GPT-API? We have the perfect solution for you! 4 | 5 | Introducing **[ChatGPT-Driver](https://youtu.be/9fCtMJQxQ4c)**, a system comprised of two components: **ChatGPT-Bridge** (referred to as **"Bridge"**) and **[ChatGPT-Executor](https://github.com/improveTheWorld/ChatGPT-Executor)** (referred to as **"Executor"**). 6 | **Bridge** is a web browser plugin compatible with Microsoft Edge and Google Chrome. It offers API-like access to **ChatGPT**. When combined with **Executor** (a server application that receives and executes Windows commands), they unlock the full potential of ChatGPT without any waiting list or additional fees. 7 | 8 | **Bridge** offers API-like access to GPT-3.5 and GPT-4 for third-party software via webSockets. 9 | Bridge provides free API-like access to GPT-3.5. It also provides free API-like access to GPT-4 if you have a ChatGPT Plus account. 10 | **✨ 🎉🌟 No fees are charged for the use of the API-like access!** 11 | 12 | We are continuously striving to maintain and improve this project. If you love our work and find it useful, consider supporting us. Every small donation will go a long way in helping us to keep this project alive and free. **💌[Donate Here](https://www.paypal.com/donate/?hosted_button_id=SJTG7U2E6PC4W)💌** 13 | 14 | To fully benefit from ChatGPT-Driver, install and set up both components. 15 | 16 | ## 🆕 Most recent Release Notes (Version 1.2.0) 17 | 18 | - Add authentification token mechanism to use ChatGPT-Executor-1.2.0 19 | - Support the newest ChatGPT page's html ( ChatGPT May 24 Version) 20 | - Add a donate link into pupup.html. If interressted you may do it directly from **[Here](https://www.paypal.com/donate/?hosted_button_id=SJTG7U2E6PC4W)** 21 | 22 | 23 | **Note:** While ChatGPT-Driver has been significantly improved and tested, there may still be potential bugs and limitations. We appreciate your understanding and welcome any feedback to help us enhance the system. 24 | 25 | ## 🌟 Features 26 | 27 | - 🔗 Seamlessly connects ChatGPT with third-party software 28 | - 🌐 Utilizes WebSocket for real-time communication 29 | - 🤖 Supports both GPT-3.5 and GPT-4 30 | - 🆓 Free API-like access to GPT-3.5 and GPT-4 with a ChatGPT Plus account 31 | - 📚 Enables ChatGPT to read large files that exceed the size of a single prompt 32 | 33 | ## 🔧 Installation and Usage 34 | 35 | To utilize ChatGPT-Driver, you'll need to install both the Bridge plugin and the Executor server application. 36 | 37 | ### ChatGPT-Bridge 38 | 39 | Follow the instructions in the [Getting Started](https://github.com/improveTheWorld/ChatGPT-Bridge#getting-started) section to install the Bridge plugin. 40 | 41 | ### ChatGPT-Executor 42 | 43 | You can download and install ChatGPT-Executor-1.2.0 directly from [Here](https://bit.ly/46rz4zE). For more information you may visit the [Executor GitHub Repository](https://github.com/improveTheWorld/ChatGPT-Executor) and follow the instructions. 44 | You also can download the correct version of ChatGPT-Executor which is compatible of your ChatGPT-Bridge version , from the ChatGPT-Bridge popup. 45 | 1. click on Entensions button ( on the top left corner of your web navigator) : 46 | 47 | ![popup_1.png](./src/assets/Usage/popup_1.png) 48 | 49 | 2. From displayed the entension list , select the chatGPT-Bridge, the popup will be displayed 50 | 51 | ![popup._2.png](./src/assets/Usage/popup_2.png) 52 | 53 | 54 | here is how to display the ChatGPT-Bridge popup : 55 | 56 | ## 🚀 Getting Started 57 | 58 | ### Prerequisites 59 | 60 | - Microsoft Edge or Google Chrome browser 61 | - Basic understanding of browser extensions 62 | 63 | ### Installation 64 | 65 | 1. Clone the repository: 66 | 67 | git clone https://github.com/improveTheWorld/ChatGPT-Bridge.git 68 | 69 | 2. Open your browser and navigate to extensions ( `edge://extensions` or `chrome://extensions` depending on your browser). 70 | 3. Enable "Developer Mode" in the top-right corner. 71 | 4. Click on "Load Unpacked" and select the `ChatGPT-Bridge/src` folder. 72 | 5. The ChatGPT-Bridge plugin should now be visible in the extensions list and ready for use! 73 | 74 | ## 🛠️ Usage 75 | 76 | 1. After installing the plugin, go to [ChatGPT](https://chat.openai.com/chat) website. 77 | 2. The bridge popup will be displayed at the top right corner of the webpage. You may move it using your mouse if needed. 78 | 79 | * If the displayed popup is as below: 80 | 81 | ![Connecting.GIF](./src/assets/Usage/Connecting.GIF) 82 | 83 | `You forgot to launch the Executor or your third-party server, if applicable. Please start the Executor and wait. The Bridge will continuously poll for a connection until it is established.` 84 | * When the connection is established, the displayed popup should be as below: 85 | 86 | ![Start.GIF](./src/assets/Usage/Start.GIF) 87 | 88 | Start a new chat and then click the start button to begin bridging between your ChatGPT AI and the third-party software (the Executor). 89 | 90 | When you click start with a new chat page, the Bridge plugin will empty the first prompt and send it. The first prompt is intended to teach CHATGPT the communication protocol to use with the Executor. 91 | 92 | Once ChatGPT gets all the initial instructions, it will ask you for its first task. Assign one and watch the magic work. 93 | 94 | `As an example of use, we asked ChatGPT to troubleshoot our WiFi card. We had an issue that the Windows network diagnostic tools were unable to detect. ChatGPT, after trying different approaches using our ChatGPT-Bridge system, was able to fix it for us.`[Video](https://youtu.be/9fCtMJQxQ4c) 95 | 96 | --- 97 | * When you are done and want to stop using the bridge, just click the stop button: 98 | 99 | ![Stop.GIF](./src/assets/Usage/Stop.GIF) 100 | 101 | 3. The default WebSocket communication between the Bridge and the third-party software is done over port 8181. You can change the port in the config.json file if needed. 102 | 4. You can find the initial prompt text in the file firstPrompt.txt. You may customize it for your personal needs if you want. 103 | 5. Two modes of communication are available: 104 | 105 | * Wait for a complete GPT message before sending it to the third-party software (default mode). 106 | * Stream the message while it's being received from GPT (enable this by setting "streamingMode": true in the config.json file). 107 | 6. If you want to use only the Bridge plugin with your third-party software, your software should act as a server and listen on the correct port for a connection. Once the plugin is installed and launched, it will automatically request a connection. 108 | 109 | **FROM VERSION 1.1.0 AND LATER** 110 | 111 | If you are using a ChatGPT Plus account, a countdown of available message credits will be displayed once you start using GPT-4 (as only 25 messages per 3 hours are allowed). 112 | 113 | ![Stop.GIF](./src/assets/Usage/CountDown.GIF) 114 | 115 | The countdown will also display a timer counting down until the message credits are refilled 116 | 117 | 121 | 122 | ## 📧 Contributing 123 | 124 | We welcome contributions! If you'd like to contribute, please follow these steps: 125 | 126 | 1. Fork the repository. 127 | 2. Create your feature branch (`git checkout -b feature/your-feature`). 128 | 3. Commit your changes (`git commit -am 'Add some feature'`). 129 | 4. Push to the branch (`git push origin feature/your-feature`). 130 | 5. Open a Pull Request. 131 | 132 | Please read our [Contributing Guidelines](./CONTRIBUTING.md) for more details. 133 | 134 | ## ⚙️ Possible improvements 135 | 136 | * See the [IMPROVEMENTS](./IMPROVEMENTS.md) file. 137 | 138 | ## 🔐 License 139 | 140 | * This project is licensed under the Apache V2.0 for free software use - see the [LICENSE](./LICENSE-APACHE.txt) file for details. 141 | * For commercial software use, see the [LICENSE\_NOTICE](./LICENSE_NOTICE.md) file. 142 | 143 | ## 📬 Contact 144 | 145 | If you have any questions or suggestions, please feel free to reach out to us: 146 | 147 | * [Tec-Net](mailto:tecnet.paris@gmail.com) 148 | 149 | 150 | 151 | ## 🎉 Acknowledgments 152 | 153 | * [OpenAI](https://www.openai.com/) for the [ChatGPT](https://chat.openai.com/chat) website 154 | * [Google](https://www.google.com/chrome/) and [Microsoft](https://www.microsoft.com/en-us/edge) for providing the browser platform 155 | * All contributors who have helped improve ChatGPT-Bridge 156 | * The amazing open-source community for their invaluable resources and inspiration 157 | * Our users and testers for providing essential feedback that helps us improve ChatGPT-Bridge 158 | 159 | **Join us on this exciting journey to unlock the unlimited power and potential of ChatGPT! Stay tuned for future updates and the upcoming release of the other part of the project, which will bring even more groundbreaking features and possibilities. Together, we can revolutionize the way we interact with AI-powered language models!** 160 | -------------------------------------------------------------------------------- /LICENSE-APACHE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /src/content.js: -------------------------------------------------------------------------------- 1 | // # File: content.js 2 | // # Software: ChatGPT-Bridge 3 | // # Purpose: Provide third-party software with the capability to utilize ChatGPT. 4 | // # 5 | // # Copyright © 2023 Tec-Net 6 | // # 7 | // # Dual License Notice 8 | // # 9 | // # For Free Software Projects: 10 | // # This software is licensed under the Apache License, Version 2.0; 11 | // # you may not use this file except in compliance with the License. 12 | // # You may obtain a copy of the License at 13 | // # 14 | // # http://www.apache.org/licenses/LICENSE-2.0 15 | // # 16 | // # For Non-Free Software Projects: 17 | // # This software requires a commercial license. Please contact the author at 18 | // # tecnet.paris@gmail.com to discuss licensing terms and pricing. 19 | // # 20 | // # Unless required by applicable law or agreed to in writing, software 21 | // # distributed under the License is distributed on an "AS IS" BASIS, 22 | // # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 23 | // # See the License for the specific language governing permissions and 24 | // # limitations under the License. 25 | 26 | let lastSentMessage = ''; 27 | let previousMessage = ''; 28 | let previousMessageTimestamp = 0; 29 | let mostRecentMessagePollingIntervalId = null; 30 | let reconnectionPollIntervalId = null; 31 | let connectionStatusNotificationIntervalId = null; 32 | let config = null; 33 | let connectionStatus = 'connecting'; 34 | let ws = null 35 | let firstPrompt = null; 36 | let key = null ; 37 | let isAuthenticated = false; 38 | 39 | let textarea = document.querySelector('#prompt-textarea') 40 | 41 | let sendButton = null; 42 | 43 | function getMostRecentMessage() { 44 | const messageElement = document.querySelector('article:last-of-type .markdown.prose'); 45 | 46 | if (!messageElement) return; 47 | 48 | return messageElement.innerText.trim(); 49 | 50 | } 51 | 52 | function checkForNewCommands() { 53 | if (!config) return; 54 | 55 | 56 | const currentMessage = getMostRecentMessage(); 57 | console.log("new commands :" + currentMessage ); 58 | // Continue reading the most recent received message until it doesn't change during the defined time 59 | if (currentMessage && (currentMessage !== previousMessage)) { 60 | 61 | //Streaming mode management: to test 62 | if (config.streamingMode) { 63 | const appendedMessage = currentMessage.slice(previousMessage.length).trim(); 64 | //console.log(appendedMessage); 65 | sendMessageToWebSocketServer(appendedMessage); 66 | } 67 | 68 | //update current 69 | previousMessage = currentMessage; 70 | previousMessageTimestamp = Date.now(); 71 | 72 | // if (currentMessage == previousMessage) && waiting period reached 73 | } else if (Date.now() - previousMessageTimestamp >= config.messageCompletionTime && !config.streamingMode) { 74 | 75 | if (currentMessage && (currentMessage !== lastSentMessage)) { 76 | lastSentMessage = currentMessage; 77 | //console.log('Most recent received message:', completeMessage); 78 | sendMessageToWebSocketServer(lastSentMessage); 79 | } 80 | } 81 | } 82 | 83 | function adjustTextAreaHeight() { 84 | // Adjust the textarea height based on the content length 85 | const rows = Math.ceil((textarea.innerText.length) / 88); 86 | const height = rows * 24; 87 | textarea.height = height + 'px'; 88 | } 89 | 90 | function AnswerChatGPT(text) 91 | { 92 | // Fetching the textarea and the sendButton with more specific selector 93 | textarea = document.querySelector('#prompt-textarea'); 94 | 95 | // Focus on the textarea and simulate typing 96 | textarea.focus(); 97 | setNativeValue(textarea,text); 98 | adjustTextAreaHeight(); 99 | 100 | // click the send button when enabled 101 | clickSendButtonWhenEnabled(); 102 | 103 | return ; 104 | } 105 | 106 | function clickSendButtonWhenEnabled() 107 | { 108 | sendButton = document.querySelector('[data-testid="send-button"]'); 109 | if(sendButton && !sendButton.disabled) 110 | { 111 | sendButton.click(); 112 | } 113 | else 114 | { 115 | setTimeout(() => { 116 | 117 | clickSendButtonWhenEnabled(); 118 | },50); 119 | } 120 | 121 | } 122 | 123 | function setNativeValue(element, text) { 124 | let lastValue = element.innerText; 125 | element.innerText = text; 126 | let event = new Event("input", { target: element, bubbles: true }); 127 | // React 15 128 | event.simulated = true; 129 | // React 16-17 130 | let tracker = element._valueTracker; 131 | if (tracker) { 132 | tracker.setValue(lastValue); 133 | } 134 | element.dispatchEvent(event); 135 | } 136 | 137 | 138 | function isSendError() 139 | { 140 | return (document.querySelector('form.stretch div.relative > div:first-child').textContent.trim() === 'There was an error generating a responseRegenerate response'); 141 | } 142 | 143 | function notifyConnectionStatus() { 144 | emitEvent(connectionStatus); 145 | } 146 | 147 | 148 | function encryptStringAES(message, key) { 149 | const iv = CryptoJS.lib.WordArray.random(128/8); // generate a random initialization vector 150 | const encrypted = CryptoJS.AES.encrypt(message, CryptoJS.enc.Base64.parse(key), { 151 | iv: iv, 152 | mode: CryptoJS.mode.CBC 153 | }); 154 | 155 | // Concatenate the random IV and the cipher text, then convert to a base64 string 156 | const encryptedMessage = CryptoJS.enc.Base64.stringify(iv.concat(encrypted.ciphertext)); 157 | return encryptedMessage; 158 | } 159 | 160 | function extractKey(str) { 161 | const regex = /^KEY:(.*)$/; 162 | const match = str.match(regex); 163 | 164 | if (match && match.length === 2) { 165 | return match[1]; 166 | } 167 | 168 | return null; 169 | } 170 | 171 | 172 | function connectWebSocket() { 173 | if (connectionStatus != 'disconnected') { 174 | // Check if the WebSocket is already connected before creating a new connection 175 | if (ws &&(ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING) ){ 176 | console.log("connectWebSocket : already connected or connecting !"); 177 | return; 178 | } 179 | 180 | ws = new WebSocket(`ws://127.0.0.1:${config.communicationPort}`); 181 | 182 | ws.addEventListener('message', (event) => { 183 | 184 | const output = event.data; 185 | 186 | if(config.authenticationNeeded && !isAuthenticated) 187 | { 188 | tempKey = extractKey(output); 189 | 190 | if(tempKey != null) 191 | { 192 | console.log("New Key receiced : "+ tempKey); 193 | key = tempKey; 194 | save('funKey', key); 195 | 196 | } 197 | else if(key!= null) 198 | { 199 | console.log("Authentication question received. Sending Answer"); 200 | ws.send( encryptStringAES(CryptoJS.SHA256(output).toString(),key)); 201 | 202 | } 203 | else 204 | { 205 | console.error("not authentified, authentication needed, but key value is "+key); 206 | } 207 | 208 | if(key!= null) 209 | { 210 | isAuthenticated = true; 211 | 212 | if (connectionStatus != 'disconnected') { 213 | connectionStatus = 'connected'; 214 | } 215 | } 216 | 217 | } 218 | else 219 | { 220 | console.log("New message received :", output); 221 | AnswerChatGPT(output); 222 | } 223 | }); 224 | 225 | ws.addEventListener('open', (event) => { 226 | if( !config.authenticationNeeded && (connectionStatus != 'disconnected') ) 227 | { 228 | connectionStatus = 'connected'; 229 | } 230 | }); 231 | 232 | ws.addEventListener('error', (event) => { 233 | if (connectionStatus != 'disconnected') { 234 | connectionStatus = 'connecting'; 235 | setTimeout(() => { 236 | connectWebSocket(); 237 | }, config.reconnectInterval); 238 | } 239 | }); 240 | 241 | ws.addEventListener('close', (event) => { 242 | isAuthenticated = false; 243 | if (connectionStatus != 'disconnected') { 244 | connectionStatus = 'connecting'; 245 | setTimeout(() => { 246 | connectWebSocket(); 247 | }, config.reconnectInterval); 248 | } 249 | }); 250 | } 251 | } 252 | 253 | async function loadConfig() { 254 | try 255 | { 256 | const storedConfig = await getStored('config'); 257 | if (storedConfig) 258 | { 259 | config = storedConfig; 260 | } else 261 | { 262 | const response = await fetch(chrome.runtime.getURL('config.json')); 263 | config = await response.json(); 264 | await save('config',config); // Save the default config to local storage 265 | } 266 | } 267 | catch (error) 268 | { 269 | console.error('Error loading config:', error); 270 | } 271 | } 272 | 273 | 274 | async function load(itemName, variable, defaultValue) 275 | { 276 | try 277 | { 278 | const temp = await getStored(itemName); 279 | console.log("getStored("+itemName+") returned :", temp); 280 | if (temp) 281 | { 282 | return temp; 283 | } 284 | else 285 | { 286 | if (defaultValue) 287 | { 288 | await save(itemName,defaultValue); // Save the default config to local storage 289 | } 290 | 291 | return defaultValue; 292 | } 293 | } 294 | catch (error) 295 | { 296 | console.error('Error loading config:', error); 297 | if (defaultValue) 298 | { 299 | await save(itemName,defaultValue); // Save the default config to local storage 300 | } 301 | 302 | return defaultValue; 303 | } 304 | } 305 | 306 | 307 | function getStored(itemName) { 308 | return new Promise((resolve, reject) => { 309 | chrome.storage.local.get(itemName, (result) => { 310 | if (chrome.runtime.lastError) { 311 | console.error('Error retrieving '+ itemName + ' :', chrome.runtime.lastError); 312 | reject(chrome.runtime.lastError); 313 | } else { 314 | console.log( itemName + " loaded: "+ result[itemName]); 315 | resolve(result[itemName]); 316 | } 317 | }); 318 | }); 319 | } 320 | 321 | function save(itemName, item ) { 322 | return new Promise((resolve, reject) => { 323 | chrome.storage.local.set({ [itemName] : item }, () => { 324 | if (chrome.runtime.lastError) { 325 | console.error('Error saving ' + itemName +' :', chrome.runtime.lastError); 326 | reject(chrome.runtime.lastError); 327 | } else { 328 | console.log(itemName + ' saved successfully as' + item); 329 | resolve(); 330 | } 331 | }); 332 | }); 333 | } 334 | 335 | async function loadTimestamps() { 336 | try { 337 | const temp = await getStored('timestamps') 338 | 339 | if (temp) { 340 | 341 | timestamps = temp; 342 | 343 | } 344 | } catch (error) { 345 | console.error('Error loading timestamps:', error); 346 | } 347 | 348 | if (chrome.runtime.lastError) { 349 | reject(chrome.runtime.lastError); 350 | } 351 | } 352 | 353 | function saveTimestamps(timestamps) { 354 | return save('timestamps', timestamps); 355 | } 356 | 357 | 358 | 359 | async function loadfirstPrompt() { 360 | try { 361 | const response = await fetch(chrome.runtime.getURL('firstPrompt.txt')); 362 | firstPrompt = await response.text(); 363 | } catch (error) { 364 | //console.error('Error loading firstPrompt:', error); 365 | if (chrome.runtime.lastError) { 366 | console.error('Error retrieving config:', chrome.runtime.lastError); 367 | reject(chrome.runtime.lastError); 368 | } 369 | 370 | } 371 | 372 | 373 | } 374 | 375 | function emitEvent(name, detail = null) { 376 | const event = new CustomEvent(name, { detail }); 377 | window.dispatchEvent(event); 378 | } 379 | 380 | function loadFontAwesomeCSS() { 381 | const link = document.createElement('link'); 382 | link.rel = 'stylesheet'; 383 | link.type = 'text/css'; 384 | link.href = chrome.runtime.getURL('./assets/css/all.min.css'); 385 | document.head.appendChild(link); 386 | } 387 | 388 | function injectPopup() { 389 | // Load Font Awesome CSS before injecting popup 390 | loadFontAwesomeCSS(); 391 | 392 | const popupHtml = ` 393 | 394 | 395 | `; 413 | 414 | const parser = new DOMParser(); 415 | const popupDOM = parser.parseFromString(popupHtml, 'text/html'); 416 | document.body.appendChild(popupDOM.querySelector('#popup-container')); 417 | 418 | // Inject the injected-popup.js script into the chat page 419 | const script = document.createElement('script'); 420 | script.src = chrome.runtime.getURL('injected-popup.js'); 421 | (document.head || document.documentElement).appendChild(script); 422 | } 423 | 424 | 425 | 426 | /////////////////////////////////////// countdown management ///////////////////////// 427 | const MAX_ALLOWED_MESSAGES_CREDIT= 25; 428 | let allowedMessagesCount = MAX_ALLOWED_MESSAGES_CREDIT; 429 | let timestamps = []; 430 | const timeLimit = 3 * 60 * 60 * 1000; // 3 hours in milliseconds 431 | 432 | 433 | async function updateTimestamps(addNewStamps) { 434 | 435 | if ( await updatePendingMessagesCredit(addNewStamps)) 436 | { 437 | save('timestamps',timestamps); 438 | 439 | timeCountDown = -1; 440 | 441 | if(timestamps.length > 0) 442 | { 443 | const now = new Date().getTime(); 444 | timeCountDown = timeLimit - (now - timestamps[0])+ 1000; 445 | } 446 | emitEvent('newCountDown', { 'countDown': MAX_ALLOWED_MESSAGES_CREDIT - timestamps.length,'timerCounDown': timeCountDown }); 447 | } 448 | } 449 | 450 | async function updatePendingMessagesCredit(addNewStamps) { 451 | 452 | const now = new Date().getTime(); 453 | let timestampsChanged = false; 454 | 455 | if (addNewStamps && (timestamps.length 0 && (now - timestamps[0]) > timeLimit) { 465 | 466 | if(!timestampsChanged) 467 | { 468 | loadTimestamps(); 469 | } 470 | timestamps.shift(); 471 | timestampsChanged = true; 472 | } 473 | 474 | 475 | // Planify the next Check 476 | if (timestamps.length > 0) { 477 | 478 | const nextMessageWindow = timeLimit - (now - timestamps[0]) + 1000; 479 | 480 | setTimeout(() => { 481 | updateTimestamps(false); 482 | }, nextMessageWindow ); 483 | console.log('Next check planned in :',nextMessageWindow); 484 | } 485 | return timestampsChanged; 486 | 487 | } 488 | 489 | async function onFeedbackSent() { 490 | if ( !isSendError() ) { 491 | lastSentMessage = ''; 492 | if(isGPT4() ) 493 | { 494 | //console.log('GPT 4 feedbacksent'); 495 | await updateTimestamps(true); 496 | } 497 | } 498 | } 499 | 500 | 501 | 502 | //////////////////////////////////////// server messages management ///////////////////////////////////////////// 503 | 504 | function sendMessageToWebSocketServer(message) { 505 | if (ws && ws.readyState === WebSocket.OPEN) { 506 | ws.send(message); 507 | } else { 508 | //console.log('WebSocket is not connected or not in the open state.'); 509 | } 510 | } 511 | 512 | function isNewChatPage() 513 | { 514 | // true if no answer received yet 515 | let isNew = (!document.querySelector('div.group:nth-last-child(2) div.markdown.prose')) 516 | if(isNew) 517 | { 518 | // for each new session check the status of the account 519 | updateGPT_PlusAccountStatus() 520 | } 521 | return isNew; 522 | } 523 | function startSendingFeedback() { 524 | 525 | 526 | //If new chat session, start by send the configuration prompt 527 | if (isNewChatPage()) { 528 | 529 | if(firstPrompt) 530 | { 531 | AnswerChatGPT(firstPrompt); 532 | } 533 | else 534 | { 535 | sendMessageToWebSocketServer("_START_NEW"); 536 | } 537 | 538 | } 539 | startMonitoringReceivedMessages(); 540 | } 541 | 542 | function stopSendingFeedback() { 543 | 544 | stopMonitoringReceivedMessages(); 545 | 546 | } 547 | 548 | ///////////////////////// Server connection Management /////////////////////////// 549 | 550 | 551 | function disconnectServer() { 552 | clearInterval(connectionStatusNotificationIntervalId); 553 | connectionStatus = 'disconnected'; 554 | if (ws && (ws.readyState !== WebSocket.CLOSED) && (ws.readyState !== WebSocket.CLOSING)) { 555 | ws.close(); 556 | } 557 | } 558 | 559 | function connectToServer() { 560 | connectionStatus = 'connecting'; 561 | connectWebSocket(); 562 | connectionStatusNotificationIntervalId = setInterval(notifyConnectionStatus, config.reconnectInterval); 563 | } 564 | 565 | let isChatGPT_PlusAccount = false 566 | function updateGPT_PlusAccountStatus() 567 | { 568 | if(document.querySelector('span.bg-yellow-200.text-yellow-900.py-0\\.5.px-1\\.5.text-xs.md\\:text-sm.rounded-md.uppercase')) 569 | { 570 | isChatGPT_PlusAccount = true; 571 | } 572 | } 573 | 574 | 575 | 576 | 577 | function isGPT4() 578 | { 579 | //when the chat page is just loaded 580 | let titleElement = document.querySelector('.truncate > span.flex.h-6.items-center.gap-1.truncate'); 581 | if(!titleElement){ 582 | titleElement = document.querySelector('.flex.w-full.items-center.justify-center.gap-1.border-b'); 583 | } 584 | if(!titleElement) 585 | { 586 | titleElement = document.querySelector('div[class*="dark\\:text-gray-300"]'); 587 | } 588 | if(!titleElement) 589 | { 590 | return false; 591 | } 592 | 593 | const regex = new RegExp(`\\b${'GPT-4'}\\b`, 'i'); 594 | return regex.test(titleElement.innerText); 595 | 596 | } 597 | 598 | 599 | // Helper function to check if an element or any of its ancestors matches the condition 600 | function isSendButton(element) { 601 | while (element) { 602 | if ( 603 | element.tagName === 'BUTTON' && 604 | element.parentElement.querySelector('textarea.w-full') !== null 605 | ) { 606 | return true; 607 | } 608 | element = element.parentElement; 609 | } 610 | return false; 611 | } 612 | 613 | // Helper function to check if an element or any of its ancestors is the desired textarea 614 | function isTextArea(element) { 615 | while (element) { 616 | if ( 617 | element.tagName === 'TEXTAREA' && 618 | element.classList.contains('w-full') 619 | ) { 620 | return true; 621 | } 622 | element = element.parentElement; 623 | } 624 | return false; 625 | } 626 | 627 | 628 | ///////////////////////// Main Program /////////////////////////// 629 | 630 | window.addEventListener('startSendingFeedback', () => { 631 | console.log(' content.js: startSendingFeedback received '); 632 | startSendingFeedback(); 633 | }); 634 | 635 | 636 | window.addEventListener('stopSendingFeedback', () => { 637 | //console.log(' content.js: stopSendingFeedback received '); 638 | stopSendingFeedback(); 639 | }); 640 | 641 | window.addEventListener('disconnect', () => { 642 | //console.log(' content.js: disconnect received '); 643 | disconnectServer(); 644 | }); 645 | 646 | window.addEventListener('connect', () => { 647 | //console.log(' content.js: connect received '); 648 | connectToServer(); 649 | }); 650 | 651 | 652 | 653 | //Attaching the event listener to the document 654 | document.addEventListener('keydown', (event) => { 655 | // Check if the event target (or any of its ancestors) is the desired textarea 656 | if (isTextArea(event.target)) { 657 | // Check if the Enter key was pressed 658 | if (event.key === 'Enter' ) { 659 | 660 | // Wait for a brief delay (e.g., 100 milliseconds) 661 | setTimeout(() => { 662 | // Check if the textarea still contains the text 663 | if (event.target.value !== '') { 664 | // The Enter keypress was not considered as validation, handle the false Enter case here 665 | //console.log('False Enter detected'); 666 | } else { 667 | 668 | // The Enter keypress was considered as validation, continue with your onFeedbackSent() function 669 | onFeedbackSent(); 670 | } 671 | }, config.messageCompletionTime-500); 672 | } 673 | } 674 | }); 675 | 676 | // Attaching the event listener to the document 677 | document.addEventListener('click', (event) => { 678 | // Check if the clicked element (or any of its ancestors) matches the condition 679 | if (isSendButton(event.target)) { 680 | setTimeout(() => { 681 | onFeedbackSent(); 682 | },config.messageCompletionTime-500); 683 | } 684 | }); 685 | 686 | // Add an event listener for the 'message' event 687 | window.addEventListener('message', (event) => { 688 | // Check if the message is of type 'popupReady' 689 | if (event.data && event.data.type === 'popupReady') { 690 | onPopupReady(); 691 | } 692 | }); 693 | 694 | function stopMonitoringReceivedMessages() 695 | { 696 | sendMessageToWebSocketServer("_STOP_"); 697 | clearInterval( mostRecentMessagePollingIntervalId); 698 | 699 | } 700 | 701 | function startMonitoringReceivedMessages() 702 | { 703 | lastSentMessage = ''; 704 | previousMessage = ''; 705 | previousMessageTimestamp = 0; 706 | 707 | if (mostRecentMessagePollingIntervalId) { 708 | clearInterval(mostRecentMessagePollingIntervalId); 709 | } 710 | 711 | mostRecentMessagePollingIntervalId = setInterval(checkForNewCommands, config.pollingFrequency); 712 | } 713 | 714 | 715 | async function init() { 716 | await loadConfig(); 717 | await loadfirstPrompt(); 718 | key = await load('funKey', key, null) 719 | console.log("loaded key : " + key); 720 | injectPopup(); 721 | 722 | 723 | //Start Monitoring 724 | connectToServer(); 725 | await loadTimestamps(); 726 | await updateTimestamps(false); 727 | //startMonitoringReceivedMessages(); 728 | // Wait for the popup to be ready before emitting the event 729 | document.addEventListener('popupReady', function() { 730 | if( isGPT4() || timestamps.length >0) { 731 | const now = new Date().getTime(); 732 | emitEvent('newCountDown', { 'countDown': MAX_ALLOWED_MESSAGES_CREDIT - timestamps.length,'timerCounDown':timeLimit - ( now - timestamps[0])+ 1000 }); 733 | } 734 | }); 735 | 736 | 737 | } 738 | 739 | init(); -------------------------------------------------------------------------------- /src/crypto-js.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports?module.exports=exports=e():"function"==typeof define&&define.amd?define([],e):t.CryptoJS=e()}(this,function(){var h,t,e,r,i,n,f,o,s,c,a,l,d,m,x,b,H,z,A,u,p,_,v,y,g,B,w,k,S,C,D,E,R,M,F,P,W,O,I,U,K,X,L,j,N,T,q,Z,V,G,J,$,Q,Y,tt,et,rt,it,nt,ot,st,ct,at,ht,lt,ft,dt,ut,pt,_t,vt,yt,gt,Bt,wt,kt,St,bt=bt||function(l){var t;if("undefined"!=typeof window&&window.crypto&&(t=window.crypto),!t&&"undefined"!=typeof window&&window.msCrypto&&(t=window.msCrypto),!t&&"undefined"!=typeof global&&global.crypto&&(t=global.crypto),!t&&"function"==typeof require)try{t=require("crypto")}catch(t){}function i(){if(t){if("function"==typeof t.getRandomValues)try{return t.getRandomValues(new Uint32Array(1))[0]}catch(t){}if("function"==typeof t.randomBytes)try{return t.randomBytes(4).readInt32LE()}catch(t){}}throw new Error("Native crypto module could not be used to get secure random number.")}var r=Object.create||function(t){var e;return n.prototype=t,e=new n,n.prototype=null,e};function n(){}var e={},o=e.lib={},s=o.Base={extend:function(t){var e=r(this);return t&&e.mixIn(t),e.hasOwnProperty("init")&&this.init!==e.init||(e.init=function(){e.$super.init.apply(this,arguments)}),(e.init.prototype=e).$super=this,e},create:function(){var t=this.extend();return t.init.apply(t,arguments),t},init:function(){},mixIn:function(t){for(var e in t)t.hasOwnProperty(e)&&(this[e]=t[e]);t.hasOwnProperty("toString")&&(this.toString=t.toString)},clone:function(){return this.init.prototype.extend(this)}},f=o.WordArray=s.extend({init:function(t,e){t=this.words=t||[],this.sigBytes=null!=e?e:4*t.length},toString:function(t){return(t||a).stringify(this)},concat:function(t){var e=this.words,r=t.words,i=this.sigBytes,n=t.sigBytes;if(this.clamp(),i%4)for(var o=0;o>>2]>>>24-o%4*8&255;e[i+o>>>2]|=s<<24-(i+o)%4*8}else for(o=0;o>>2]=r[o>>>2];return this.sigBytes+=n,this},clamp:function(){var t=this.words,e=this.sigBytes;t[e>>>2]&=4294967295<<32-e%4*8,t.length=l.ceil(e/4)},clone:function(){var t=s.clone.call(this);return t.words=this.words.slice(0),t},random:function(t){for(var e=[],r=0;r>>2]>>>24-n%4*8&255;i.push((o>>>4).toString(16)),i.push((15&o).toString(16))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>3]|=parseInt(t.substr(i,2),16)<<24-i%8*4;return new f.init(r,e/2)}},h=c.Latin1={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>24-n%4*8&255;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>2]|=(255&t.charCodeAt(i))<<24-i%4*8;return new f.init(r,e)}},d=c.Utf8={stringify:function(t){try{return decodeURIComponent(escape(h.stringify(t)))}catch(t){throw new Error("Malformed UTF-8 data")}},parse:function(t){return h.parse(unescape(encodeURIComponent(t)))}},u=o.BufferedBlockAlgorithm=s.extend({reset:function(){this._data=new f.init,this._nDataBytes=0},_append:function(t){"string"==typeof t&&(t=d.parse(t)),this._data.concat(t),this._nDataBytes+=t.sigBytes},_process:function(t){var e,r=this._data,i=r.words,n=r.sigBytes,o=this.blockSize,s=n/(4*o),c=(s=t?l.ceil(s):l.max((0|s)-this._minBufferSize,0))*o,a=l.min(4*c,n);if(c){for(var h=0;h>>32-e}function Dt(t,e,r,i){var n,o=this._iv;o?(n=o.slice(0),this._iv=void 0):n=this._prevBlock,i.encryptBlock(n,0);for(var s=0;s>24&255)){var e=t>>16&255,r=t>>8&255,i=255&t;255===e?(e=0,255===r?(r=0,255===i?i=0:++i):++r):++e,t=0,t+=e<<16,t+=r<<8,t+=i}else t+=1<<24;return t}function Rt(){for(var t=this._X,e=this._C,r=0;r<8;r++)ft[r]=e[r];e[0]=e[0]+1295307597+this._b|0,e[1]=e[1]+3545052371+(e[0]>>>0>>0?1:0)|0,e[2]=e[2]+886263092+(e[1]>>>0>>0?1:0)|0,e[3]=e[3]+1295307597+(e[2]>>>0>>0?1:0)|0,e[4]=e[4]+3545052371+(e[3]>>>0>>0?1:0)|0,e[5]=e[5]+886263092+(e[4]>>>0>>0?1:0)|0,e[6]=e[6]+1295307597+(e[5]>>>0>>0?1:0)|0,e[7]=e[7]+3545052371+(e[6]>>>0>>0?1:0)|0,this._b=e[7]>>>0>>0?1:0;for(r=0;r<8;r++){var i=t[r]+e[r],n=65535&i,o=i>>>16,s=((n*n>>>17)+n*o>>>15)+o*o,c=((4294901760&i)*i|0)+((65535&i)*i|0);dt[r]=s^c}t[0]=dt[0]+(dt[7]<<16|dt[7]>>>16)+(dt[6]<<16|dt[6]>>>16)|0,t[1]=dt[1]+(dt[0]<<8|dt[0]>>>24)+dt[7]|0,t[2]=dt[2]+(dt[1]<<16|dt[1]>>>16)+(dt[0]<<16|dt[0]>>>16)|0,t[3]=dt[3]+(dt[2]<<8|dt[2]>>>24)+dt[1]|0,t[4]=dt[4]+(dt[3]<<16|dt[3]>>>16)+(dt[2]<<16|dt[2]>>>16)|0,t[5]=dt[5]+(dt[4]<<8|dt[4]>>>24)+dt[3]|0,t[6]=dt[6]+(dt[5]<<16|dt[5]>>>16)+(dt[4]<<16|dt[4]>>>16)|0,t[7]=dt[7]+(dt[6]<<8|dt[6]>>>24)+dt[5]|0}function Mt(){for(var t=this._X,e=this._C,r=0;r<8;r++)wt[r]=e[r];e[0]=e[0]+1295307597+this._b|0,e[1]=e[1]+3545052371+(e[0]>>>0>>0?1:0)|0,e[2]=e[2]+886263092+(e[1]>>>0>>0?1:0)|0,e[3]=e[3]+1295307597+(e[2]>>>0>>0?1:0)|0,e[4]=e[4]+3545052371+(e[3]>>>0>>0?1:0)|0,e[5]=e[5]+886263092+(e[4]>>>0>>0?1:0)|0,e[6]=e[6]+1295307597+(e[5]>>>0>>0?1:0)|0,e[7]=e[7]+3545052371+(e[6]>>>0>>0?1:0)|0,this._b=e[7]>>>0>>0?1:0;for(r=0;r<8;r++){var i=t[r]+e[r],n=65535&i,o=i>>>16,s=((n*n>>>17)+n*o>>>15)+o*o,c=((4294901760&i)*i|0)+((65535&i)*i|0);kt[r]=s^c}t[0]=kt[0]+(kt[7]<<16|kt[7]>>>16)+(kt[6]<<16|kt[6]>>>16)|0,t[1]=kt[1]+(kt[0]<<8|kt[0]>>>24)+kt[7]|0,t[2]=kt[2]+(kt[1]<<16|kt[1]>>>16)+(kt[0]<<16|kt[0]>>>16)|0,t[3]=kt[3]+(kt[2]<<8|kt[2]>>>24)+kt[1]|0,t[4]=kt[4]+(kt[3]<<16|kt[3]>>>16)+(kt[2]<<16|kt[2]>>>16)|0,t[5]=kt[5]+(kt[4]<<8|kt[4]>>>24)+kt[3]|0,t[6]=kt[6]+(kt[5]<<16|kt[5]>>>16)+(kt[4]<<16|kt[4]>>>16)|0,t[7]=kt[7]+(kt[6]<<8|kt[6]>>>24)+kt[5]|0}return h=bt.lib.WordArray,bt.enc.Base64={stringify:function(t){var e=t.words,r=t.sigBytes,i=this._map;t.clamp();for(var n=[],o=0;o>>2]>>>24-o%4*8&255)<<16|(e[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|e[o+2>>>2]>>>24-(o+2)%4*8&255,c=0;c<4&&o+.75*c>>6*(3-c)&63));var a=i.charAt(64);if(a)for(;n.length%4;)n.push(a);return n.join("")},parse:function(t){var e=t.length,r=this._map,i=this._reverseMap;if(!i){i=this._reverseMap=[];for(var n=0;n>>6-o%4*2,a=s|c;i[n>>>2]|=a<<24-n%4*8,n++}return h.create(i,n)}(t,e,i)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},function(l){var t=bt,e=t.lib,r=e.WordArray,i=e.Hasher,n=t.algo,H=[];!function(){for(var t=0;t<64;t++)H[t]=4294967296*l.abs(l.sin(t+1))|0}();var o=n.MD5=i.extend({_doReset:function(){this._hash=new r.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(t,e){for(var r=0;r<16;r++){var i=e+r,n=t[i];t[i]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8)}var o=this._hash.words,s=t[e+0],c=t[e+1],a=t[e+2],h=t[e+3],l=t[e+4],f=t[e+5],d=t[e+6],u=t[e+7],p=t[e+8],_=t[e+9],v=t[e+10],y=t[e+11],g=t[e+12],B=t[e+13],w=t[e+14],k=t[e+15],S=o[0],m=o[1],x=o[2],b=o[3];S=z(S,m,x,b,s,7,H[0]),b=z(b,S,m,x,c,12,H[1]),x=z(x,b,S,m,a,17,H[2]),m=z(m,x,b,S,h,22,H[3]),S=z(S,m,x,b,l,7,H[4]),b=z(b,S,m,x,f,12,H[5]),x=z(x,b,S,m,d,17,H[6]),m=z(m,x,b,S,u,22,H[7]),S=z(S,m,x,b,p,7,H[8]),b=z(b,S,m,x,_,12,H[9]),x=z(x,b,S,m,v,17,H[10]),m=z(m,x,b,S,y,22,H[11]),S=z(S,m,x,b,g,7,H[12]),b=z(b,S,m,x,B,12,H[13]),x=z(x,b,S,m,w,17,H[14]),S=A(S,m=z(m,x,b,S,k,22,H[15]),x,b,c,5,H[16]),b=A(b,S,m,x,d,9,H[17]),x=A(x,b,S,m,y,14,H[18]),m=A(m,x,b,S,s,20,H[19]),S=A(S,m,x,b,f,5,H[20]),b=A(b,S,m,x,v,9,H[21]),x=A(x,b,S,m,k,14,H[22]),m=A(m,x,b,S,l,20,H[23]),S=A(S,m,x,b,_,5,H[24]),b=A(b,S,m,x,w,9,H[25]),x=A(x,b,S,m,h,14,H[26]),m=A(m,x,b,S,p,20,H[27]),S=A(S,m,x,b,B,5,H[28]),b=A(b,S,m,x,a,9,H[29]),x=A(x,b,S,m,u,14,H[30]),S=C(S,m=A(m,x,b,S,g,20,H[31]),x,b,f,4,H[32]),b=C(b,S,m,x,p,11,H[33]),x=C(x,b,S,m,y,16,H[34]),m=C(m,x,b,S,w,23,H[35]),S=C(S,m,x,b,c,4,H[36]),b=C(b,S,m,x,l,11,H[37]),x=C(x,b,S,m,u,16,H[38]),m=C(m,x,b,S,v,23,H[39]),S=C(S,m,x,b,B,4,H[40]),b=C(b,S,m,x,s,11,H[41]),x=C(x,b,S,m,h,16,H[42]),m=C(m,x,b,S,d,23,H[43]),S=C(S,m,x,b,_,4,H[44]),b=C(b,S,m,x,g,11,H[45]),x=C(x,b,S,m,k,16,H[46]),S=D(S,m=C(m,x,b,S,a,23,H[47]),x,b,s,6,H[48]),b=D(b,S,m,x,u,10,H[49]),x=D(x,b,S,m,w,15,H[50]),m=D(m,x,b,S,f,21,H[51]),S=D(S,m,x,b,g,6,H[52]),b=D(b,S,m,x,h,10,H[53]),x=D(x,b,S,m,v,15,H[54]),m=D(m,x,b,S,c,21,H[55]),S=D(S,m,x,b,p,6,H[56]),b=D(b,S,m,x,k,10,H[57]),x=D(x,b,S,m,d,15,H[58]),m=D(m,x,b,S,B,21,H[59]),S=D(S,m,x,b,l,6,H[60]),b=D(b,S,m,x,y,10,H[61]),x=D(x,b,S,m,a,15,H[62]),m=D(m,x,b,S,_,21,H[63]),o[0]=o[0]+S|0,o[1]=o[1]+m|0,o[2]=o[2]+x|0,o[3]=o[3]+b|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;e[i>>>5]|=128<<24-i%32;var n=l.floor(r/4294967296),o=r;e[15+(64+i>>>9<<4)]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8),e[14+(64+i>>>9<<4)]=16711935&(o<<8|o>>>24)|4278255360&(o<<24|o>>>8),t.sigBytes=4*(e.length+1),this._process();for(var s=this._hash,c=s.words,a=0;a<4;a++){var h=c[a];c[a]=16711935&(h<<8|h>>>24)|4278255360&(h<<24|h>>>8)}return s},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});function z(t,e,r,i,n,o,s){var c=t+(e&r|~e&i)+n+s;return(c<>>32-o)+e}function A(t,e,r,i,n,o,s){var c=t+(e&i|r&~i)+n+s;return(c<>>32-o)+e}function C(t,e,r,i,n,o,s){var c=t+(e^r^i)+n+s;return(c<>>32-o)+e}function D(t,e,r,i,n,o,s){var c=t+(r^(e|~i))+n+s;return(c<>>32-o)+e}t.MD5=i._createHelper(o),t.HmacMD5=i._createHmacHelper(o)}(Math),e=(t=bt).lib,r=e.WordArray,i=e.Hasher,n=t.algo,f=[],o=n.SHA1=i.extend({_doReset:function(){this._hash=new r.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],c=r[4],a=0;a<80;a++){if(a<16)f[a]=0|t[e+a];else{var h=f[a-3]^f[a-8]^f[a-14]^f[a-16];f[a]=h<<1|h>>>31}var l=(i<<5|i>>>27)+c+f[a];l+=a<20?1518500249+(n&o|~n&s):a<40?1859775393+(n^o^s):a<60?(n&o|n&s|o&s)-1894007588:(n^o^s)-899497514,c=s,s=o,o=n<<30|n>>>2,n=i,i=l}r[0]=r[0]+i|0,r[1]=r[1]+n|0,r[2]=r[2]+o|0,r[3]=r[3]+s|0,r[4]=r[4]+c|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[14+(64+i>>>9<<4)]=Math.floor(r/4294967296),e[15+(64+i>>>9<<4)]=r,t.sigBytes=4*e.length,this._process(),this._hash},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}}),t.SHA1=i._createHelper(o),t.HmacSHA1=i._createHmacHelper(o),function(n){var t=bt,e=t.lib,r=e.WordArray,i=e.Hasher,o=t.algo,s=[],B=[];!function(){function t(t){for(var e=n.sqrt(t),r=2;r<=e;r++)if(!(t%r))return;return 1}function e(t){return 4294967296*(t-(0|t))|0}for(var r=2,i=0;i<64;)t(r)&&(i<8&&(s[i]=e(n.pow(r,.5))),B[i]=e(n.pow(r,1/3)),i++),r++}();var w=[],c=o.SHA256=i.extend({_doReset:function(){this._hash=new r.init(s.slice(0))},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],c=r[4],a=r[5],h=r[6],l=r[7],f=0;f<64;f++){if(f<16)w[f]=0|t[e+f];else{var d=w[f-15],u=(d<<25|d>>>7)^(d<<14|d>>>18)^d>>>3,p=w[f-2],_=(p<<15|p>>>17)^(p<<13|p>>>19)^p>>>10;w[f]=u+w[f-7]+_+w[f-16]}var v=i&n^i&o^n&o,y=(i<<30|i>>>2)^(i<<19|i>>>13)^(i<<10|i>>>22),g=l+((c<<26|c>>>6)^(c<<21|c>>>11)^(c<<7|c>>>25))+(c&a^~c&h)+B[f]+w[f];l=h,h=a,a=c,c=s+g|0,s=o,o=n,n=i,i=g+(y+v)|0}r[0]=r[0]+i|0,r[1]=r[1]+n|0,r[2]=r[2]+o|0,r[3]=r[3]+s|0,r[4]=r[4]+c|0,r[5]=r[5]+a|0,r[6]=r[6]+h|0,r[7]=r[7]+l|0},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[14+(64+i>>>9<<4)]=n.floor(r/4294967296),e[15+(64+i>>>9<<4)]=r,t.sigBytes=4*e.length,this._process(),this._hash},clone:function(){var t=i.clone.call(this);return t._hash=this._hash.clone(),t}});t.SHA256=i._createHelper(c),t.HmacSHA256=i._createHmacHelper(c)}(Math),function(){var n=bt.lib.WordArray,t=bt.enc;t.Utf16=t.Utf16BE={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>16-n%4*8&65535;i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>1]|=t.charCodeAt(i)<<16-i%2*16;return n.create(r,2*e)}};function s(t){return t<<8&4278255360|t>>>8&16711935}t.Utf16LE={stringify:function(t){for(var e=t.words,r=t.sigBytes,i=[],n=0;n>>2]>>>16-n%4*8&65535);i.push(String.fromCharCode(o))}return i.join("")},parse:function(t){for(var e=t.length,r=[],i=0;i>>1]|=s(t.charCodeAt(i)<<16-i%2*16);return n.create(r,2*e)}}}(),function(){if("function"==typeof ArrayBuffer){var t=bt.lib.WordArray,n=t.init;(t.init=function(t){if(t instanceof ArrayBuffer&&(t=new Uint8Array(t)),(t instanceof Int8Array||"undefined"!=typeof Uint8ClampedArray&&t instanceof Uint8ClampedArray||t instanceof Int16Array||t instanceof Uint16Array||t instanceof Int32Array||t instanceof Uint32Array||t instanceof Float32Array||t instanceof Float64Array)&&(t=new Uint8Array(t.buffer,t.byteOffset,t.byteLength)),t instanceof Uint8Array){for(var e=t.byteLength,r=[],i=0;i>>2]|=t[i]<<24-i%4*8;n.call(this,r,e)}else n.apply(this,arguments)}).prototype=t}}(),Math,c=(s=bt).lib,a=c.WordArray,l=c.Hasher,d=s.algo,m=a.create([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13]),x=a.create([5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]),b=a.create([11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6]),H=a.create([8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]),z=a.create([0,1518500249,1859775393,2400959708,2840853838]),A=a.create([1352829926,1548603684,1836072691,2053994217,0]),u=d.RIPEMD160=l.extend({_doReset:function(){this._hash=a.create([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(t,e){for(var r=0;r<16;r++){var i=e+r,n=t[i];t[i]=16711935&(n<<8|n>>>24)|4278255360&(n<<24|n>>>8)}var o,s,c,a,h,l,f,d,u,p,_,v=this._hash.words,y=z.words,g=A.words,B=m.words,w=x.words,k=b.words,S=H.words;l=o=v[0],f=s=v[1],d=c=v[2],u=a=v[3],p=h=v[4];for(r=0;r<80;r+=1)_=o+t[e+B[r]]|0,_+=r<16?mt(s,c,a)+y[0]:r<32?xt(s,c,a)+y[1]:r<48?Ht(s,c,a)+y[2]:r<64?zt(s,c,a)+y[3]:At(s,c,a)+y[4],_=(_=Ct(_|=0,k[r]))+h|0,o=h,h=a,a=Ct(c,10),c=s,s=_,_=l+t[e+w[r]]|0,_+=r<16?At(f,d,u)+g[0]:r<32?zt(f,d,u)+g[1]:r<48?Ht(f,d,u)+g[2]:r<64?xt(f,d,u)+g[3]:mt(f,d,u)+g[4],_=(_=Ct(_|=0,S[r]))+p|0,l=p,p=u,u=Ct(d,10),d=f,f=_;_=v[1]+c+u|0,v[1]=v[2]+a+p|0,v[2]=v[3]+h+l|0,v[3]=v[4]+o+f|0,v[4]=v[0]+s+d|0,v[0]=_},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;e[i>>>5]|=128<<24-i%32,e[14+(64+i>>>9<<4)]=16711935&(r<<8|r>>>24)|4278255360&(r<<24|r>>>8),t.sigBytes=4*(e.length+1),this._process();for(var n=this._hash,o=n.words,s=0;s<5;s++){var c=o[s];o[s]=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8)}return n},clone:function(){var t=l.clone.call(this);return t._hash=this._hash.clone(),t}}),s.RIPEMD160=l._createHelper(u),s.HmacRIPEMD160=l._createHmacHelper(u),p=bt.lib.Base,_=bt.enc.Utf8,bt.algo.HMAC=p.extend({init:function(t,e){t=this._hasher=new t.init,"string"==typeof e&&(e=_.parse(e));var r=t.blockSize,i=4*r;e.sigBytes>i&&(e=t.finalize(e)),e.clamp();for(var n=this._oKey=e.clone(),o=this._iKey=e.clone(),s=n.words,c=o.words,a=0;a>>24)|4278255360&(o<<24|o>>>8),s=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),(x=r[n]).high^=s,x.low^=o}for(var c=0;c<24;c++){for(var a=0;a<5;a++){for(var h=0,l=0,f=0;f<5;f++){h^=(x=r[a+5*f]).high,l^=x.low}var d=R[a];d.high=h,d.low=l}for(a=0;a<5;a++){var u=R[(a+4)%5],p=R[(a+1)%5],_=p.high,v=p.low;for(h=u.high^(_<<1|v>>>31),l=u.low^(v<<1|_>>>31),f=0;f<5;f++){(x=r[a+5*f]).high^=h,x.low^=l}}for(var y=1;y<25;y++){var g=(x=r[y]).high,B=x.low,w=C[y];l=w<32?(h=g<>>32-w,B<>>32-w):(h=B<>>64-w,g<>>64-w);var k=R[D[y]];k.high=h,k.low=l}var S=R[0],m=r[0];S.high=m.high,S.low=m.low;for(a=0;a<5;a++)for(f=0;f<5;f++){var x=r[y=a+5*f],b=R[y],H=R[(a+1)%5+5*f],z=R[(a+2)%5+5*f];x.high=b.high^~H.high&z.high,x.low=b.low^~H.low&z.low}x=r[0];var A=E[c];x.high^=A.high,x.low^=A.low}},_doFinalize:function(){var t=this._data,e=t.words,r=(this._nDataBytes,8*t.sigBytes),i=32*this.blockSize;e[r>>>5]|=1<<24-r%32,e[(d.ceil((1+r)/i)*i>>>5)-1]|=128,t.sigBytes=4*e.length,this._process();for(var n=this._state,o=this.cfg.outputLength/8,s=o/8,c=[],a=0;a>>24)|4278255360&(l<<24|l>>>8),f=16711935&(f<<8|f>>>24)|4278255360&(f<<24|f>>>8),c.push(f),c.push(l)}return new u.init(c,o)},clone:function(){for(var t=i.clone.call(this),e=t._state=this._state.slice(0),r=0;r<25;r++)e[r]=e[r].clone();return t}});t.SHA3=i._createHelper(n),t.HmacSHA3=i._createHmacHelper(n)}(Math),function(){var t=bt,e=t.lib.Hasher,r=t.x64,i=r.Word,n=r.WordArray,o=t.algo;function s(){return i.create.apply(i,arguments)}var mt=[s(1116352408,3609767458),s(1899447441,602891725),s(3049323471,3964484399),s(3921009573,2173295548),s(961987163,4081628472),s(1508970993,3053834265),s(2453635748,2937671579),s(2870763221,3664609560),s(3624381080,2734883394),s(310598401,1164996542),s(607225278,1323610764),s(1426881987,3590304994),s(1925078388,4068182383),s(2162078206,991336113),s(2614888103,633803317),s(3248222580,3479774868),s(3835390401,2666613458),s(4022224774,944711139),s(264347078,2341262773),s(604807628,2007800933),s(770255983,1495990901),s(1249150122,1856431235),s(1555081692,3175218132),s(1996064986,2198950837),s(2554220882,3999719339),s(2821834349,766784016),s(2952996808,2566594879),s(3210313671,3203337956),s(3336571891,1034457026),s(3584528711,2466948901),s(113926993,3758326383),s(338241895,168717936),s(666307205,1188179964),s(773529912,1546045734),s(1294757372,1522805485),s(1396182291,2643833823),s(1695183700,2343527390),s(1986661051,1014477480),s(2177026350,1206759142),s(2456956037,344077627),s(2730485921,1290863460),s(2820302411,3158454273),s(3259730800,3505952657),s(3345764771,106217008),s(3516065817,3606008344),s(3600352804,1432725776),s(4094571909,1467031594),s(275423344,851169720),s(430227734,3100823752),s(506948616,1363258195),s(659060556,3750685593),s(883997877,3785050280),s(958139571,3318307427),s(1322822218,3812723403),s(1537002063,2003034995),s(1747873779,3602036899),s(1955562222,1575990012),s(2024104815,1125592928),s(2227730452,2716904306),s(2361852424,442776044),s(2428436474,593698344),s(2756734187,3733110249),s(3204031479,2999351573),s(3329325298,3815920427),s(3391569614,3928383900),s(3515267271,566280711),s(3940187606,3454069534),s(4118630271,4000239992),s(116418474,1914138554),s(174292421,2731055270),s(289380356,3203993006),s(460393269,320620315),s(685471733,587496836),s(852142971,1086792851),s(1017036298,365543100),s(1126000580,2618297676),s(1288033470,3409855158),s(1501505948,4234509866),s(1607167915,987167468),s(1816402316,1246189591)],xt=[];!function(){for(var t=0;t<80;t++)xt[t]=s()}();var c=o.SHA512=e.extend({_doReset:function(){this._hash=new n.init([new i.init(1779033703,4089235720),new i.init(3144134277,2227873595),new i.init(1013904242,4271175723),new i.init(2773480762,1595750129),new i.init(1359893119,2917565137),new i.init(2600822924,725511199),new i.init(528734635,4215389547),new i.init(1541459225,327033209)])},_doProcessBlock:function(t,e){for(var r=this._hash.words,i=r[0],n=r[1],o=r[2],s=r[3],c=r[4],a=r[5],h=r[6],l=r[7],f=i.high,d=i.low,u=n.high,p=n.low,_=o.high,v=o.low,y=s.high,g=s.low,B=c.high,w=c.low,k=a.high,S=a.low,m=h.high,x=h.low,b=l.high,H=l.low,z=f,A=d,C=u,D=p,E=_,R=v,M=y,F=g,P=B,W=w,O=k,I=S,U=m,K=x,X=b,L=H,j=0;j<80;j++){var N,T,q=xt[j];if(j<16)T=q.high=0|t[e+2*j],N=q.low=0|t[e+2*j+1];else{var Z=xt[j-15],V=Z.high,G=Z.low,J=(V>>>1|G<<31)^(V>>>8|G<<24)^V>>>7,$=(G>>>1|V<<31)^(G>>>8|V<<24)^(G>>>7|V<<25),Q=xt[j-2],Y=Q.high,tt=Q.low,et=(Y>>>19|tt<<13)^(Y<<3|tt>>>29)^Y>>>6,rt=(tt>>>19|Y<<13)^(tt<<3|Y>>>29)^(tt>>>6|Y<<26),it=xt[j-7],nt=it.high,ot=it.low,st=xt[j-16],ct=st.high,at=st.low;T=(T=(T=J+nt+((N=$+ot)>>>0<$>>>0?1:0))+et+((N+=rt)>>>0>>0?1:0))+ct+((N+=at)>>>0>>0?1:0),q.high=T,q.low=N}var ht,lt=P&O^~P&U,ft=W&I^~W&K,dt=z&C^z&E^C&E,ut=A&D^A&R^D&R,pt=(z>>>28|A<<4)^(z<<30|A>>>2)^(z<<25|A>>>7),_t=(A>>>28|z<<4)^(A<<30|z>>>2)^(A<<25|z>>>7),vt=(P>>>14|W<<18)^(P>>>18|W<<14)^(P<<23|W>>>9),yt=(W>>>14|P<<18)^(W>>>18|P<<14)^(W<<23|P>>>9),gt=mt[j],Bt=gt.high,wt=gt.low,kt=X+vt+((ht=L+yt)>>>0>>0?1:0),St=_t+ut;X=U,L=K,U=O,K=I,O=P,I=W,P=M+(kt=(kt=(kt=kt+lt+((ht=ht+ft)>>>0>>0?1:0))+Bt+((ht=ht+wt)>>>0>>0?1:0))+T+((ht=ht+N)>>>0>>0?1:0))+((W=F+ht|0)>>>0>>0?1:0)|0,M=E,F=R,E=C,R=D,C=z,D=A,z=kt+(pt+dt+(St>>>0<_t>>>0?1:0))+((A=ht+St|0)>>>0>>0?1:0)|0}d=i.low=d+A,i.high=f+z+(d>>>0>>0?1:0),p=n.low=p+D,n.high=u+C+(p>>>0>>0?1:0),v=o.low=v+R,o.high=_+E+(v>>>0>>0?1:0),g=s.low=g+F,s.high=y+M+(g>>>0>>0?1:0),w=c.low=w+W,c.high=B+P+(w>>>0>>0?1:0),S=a.low=S+I,a.high=k+O+(S>>>0>>0?1:0),x=h.low=x+K,h.high=m+U+(x>>>0>>0?1:0),H=l.low=H+L,l.high=b+X+(H>>>0>>0?1:0)},_doFinalize:function(){var t=this._data,e=t.words,r=8*this._nDataBytes,i=8*t.sigBytes;return e[i>>>5]|=128<<24-i%32,e[30+(128+i>>>10<<5)]=Math.floor(r/4294967296),e[31+(128+i>>>10<<5)]=r,t.sigBytes=4*e.length,this._process(),this._hash.toX32()},clone:function(){var t=e.clone.call(this);return t._hash=this._hash.clone(),t},blockSize:32});t.SHA512=e._createHelper(c),t.HmacSHA512=e._createHmacHelper(c)}(),Z=(q=bt).x64,V=Z.Word,G=Z.WordArray,J=q.algo,$=J.SHA512,Q=J.SHA384=$.extend({_doReset:function(){this._hash=new G.init([new V.init(3418070365,3238371032),new V.init(1654270250,914150663),new V.init(2438529370,812702999),new V.init(355462360,4144912697),new V.init(1731405415,4290775857),new V.init(2394180231,1750603025),new V.init(3675008525,1694076839),new V.init(1203062813,3204075428)])},_doFinalize:function(){var t=$._doFinalize.call(this);return t.sigBytes-=16,t}}),q.SHA384=$._createHelper(Q),q.HmacSHA384=$._createHmacHelper(Q),bt.lib.Cipher||function(){var t=bt,e=t.lib,r=e.Base,a=e.WordArray,i=e.BufferedBlockAlgorithm,n=t.enc,o=(n.Utf8,n.Base64),s=t.algo.EvpKDF,c=e.Cipher=i.extend({cfg:r.extend(),createEncryptor:function(t,e){return this.create(this._ENC_XFORM_MODE,t,e)},createDecryptor:function(t,e){return this.create(this._DEC_XFORM_MODE,t,e)},init:function(t,e,r){this.cfg=this.cfg.extend(r),this._xformMode=t,this._key=e,this.reset()},reset:function(){i.reset.call(this),this._doReset()},process:function(t){return this._append(t),this._process()},finalize:function(t){return t&&this._append(t),this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(i){return{encrypt:function(t,e,r){return h(e).encrypt(i,t,e,r)},decrypt:function(t,e,r){return h(e).decrypt(i,t,e,r)}}}});function h(t){return"string"==typeof t?w:g}e.StreamCipher=c.extend({_doFinalize:function(){return this._process(!0)},blockSize:1});var l,f=t.mode={},d=e.BlockCipherMode=r.extend({createEncryptor:function(t,e){return this.Encryptor.create(t,e)},createDecryptor:function(t,e){return this.Decryptor.create(t,e)},init:function(t,e){this._cipher=t,this._iv=e}}),u=f.CBC=((l=d.extend()).Encryptor=l.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize;p.call(this,t,e,i),r.encryptBlock(t,e),this._prevBlock=t.slice(e,e+i)}}),l.Decryptor=l.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=t.slice(e,e+i);r.decryptBlock(t,e),p.call(this,t,e,i),this._prevBlock=n}}),l);function p(t,e,r){var i,n=this._iv;n?(i=n,this._iv=void 0):i=this._prevBlock;for(var o=0;o>>2];t.sigBytes-=e}},v=(e.BlockCipher=c.extend({cfg:c.cfg.extend({mode:u,padding:_}),reset:function(){var t;c.reset.call(this);var e=this.cfg,r=e.iv,i=e.mode;this._xformMode==this._ENC_XFORM_MODE?t=i.createEncryptor:(t=i.createDecryptor,this._minBufferSize=1),this._mode&&this._mode.__creator==t?this._mode.init(this,r&&r.words):(this._mode=t.call(i,this,r&&r.words),this._mode.__creator=t)},_doProcessBlock:function(t,e){this._mode.processBlock(t,e)},_doFinalize:function(){var t,e=this.cfg.padding;return this._xformMode==this._ENC_XFORM_MODE?(e.pad(this._data,this.blockSize),t=this._process(!0)):(t=this._process(!0),e.unpad(t)),t},blockSize:4}),e.CipherParams=r.extend({init:function(t){this.mixIn(t)},toString:function(t){return(t||this.formatter).stringify(this)}})),y=(t.format={}).OpenSSL={stringify:function(t){var e=t.ciphertext,r=t.salt;return(r?a.create([1398893684,1701076831]).concat(r).concat(e):e).toString(o)},parse:function(t){var e,r=o.parse(t),i=r.words;return 1398893684==i[0]&&1701076831==i[1]&&(e=a.create(i.slice(2,4)),i.splice(0,4),r.sigBytes-=16),v.create({ciphertext:r,salt:e})}},g=e.SerializableCipher=r.extend({cfg:r.extend({format:y}),encrypt:function(t,e,r,i){i=this.cfg.extend(i);var n=t.createEncryptor(r,i),o=n.finalize(e),s=n.cfg;return v.create({ciphertext:o,key:r,iv:s.iv,algorithm:t,mode:s.mode,padding:s.padding,blockSize:t.blockSize,formatter:i.format})},decrypt:function(t,e,r,i){return i=this.cfg.extend(i),e=this._parse(e,i.format),t.createDecryptor(r,i).finalize(e.ciphertext)},_parse:function(t,e){return"string"==typeof t?e.parse(t,this):t}}),B=(t.kdf={}).OpenSSL={execute:function(t,e,r,i){i=i||a.random(8);var n=s.create({keySize:e+r}).compute(t,i),o=a.create(n.words.slice(e),4*r);return n.sigBytes=4*e,v.create({key:n,iv:o,salt:i})}},w=e.PasswordBasedCipher=g.extend({cfg:g.cfg.extend({kdf:B}),encrypt:function(t,e,r,i){var n=(i=this.cfg.extend(i)).kdf.execute(r,t.keySize,t.ivSize);i.iv=n.iv;var o=g.encrypt.call(this,t,e,n.key,i);return o.mixIn(n),o},decrypt:function(t,e,r,i){i=this.cfg.extend(i),e=this._parse(e,i.format);var n=i.kdf.execute(r,t.keySize,t.ivSize,e.salt);return i.iv=n.iv,g.decrypt.call(this,t,e,n.key,i)}})}(),bt.mode.CFB=((Y=bt.lib.BlockCipherMode.extend()).Encryptor=Y.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize;Dt.call(this,t,e,i,r),this._prevBlock=t.slice(e,e+i)}}),Y.Decryptor=Y.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=t.slice(e,e+i);Dt.call(this,t,e,i,r),this._prevBlock=n}}),Y),bt.mode.ECB=((tt=bt.lib.BlockCipherMode.extend()).Encryptor=tt.extend({processBlock:function(t,e){this._cipher.encryptBlock(t,e)}}),tt.Decryptor=tt.extend({processBlock:function(t,e){this._cipher.decryptBlock(t,e)}}),tt),bt.pad.AnsiX923={pad:function(t,e){var r=t.sigBytes,i=4*e,n=i-r%i,o=r+n-1;t.clamp(),t.words[o>>>2]|=n<<24-o%4*8,t.sigBytes+=n},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},bt.pad.Iso10126={pad:function(t,e){var r=4*e,i=r-t.sigBytes%r;t.concat(bt.lib.WordArray.random(i-1)).concat(bt.lib.WordArray.create([i<<24],1))},unpad:function(t){var e=255&t.words[t.sigBytes-1>>>2];t.sigBytes-=e}},bt.pad.Iso97971={pad:function(t,e){t.concat(bt.lib.WordArray.create([2147483648],1)),bt.pad.ZeroPadding.pad(t,e)},unpad:function(t){bt.pad.ZeroPadding.unpad(t),t.sigBytes--}},bt.mode.OFB=(et=bt.lib.BlockCipherMode.extend(),rt=et.Encryptor=et.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=this._iv,o=this._keystream;n&&(o=this._keystream=n.slice(0),this._iv=void 0),r.encryptBlock(o,0);for(var s=0;s>>8^255&n^99,h[r]=n;var o=t[l[n]=r],s=t[o],c=t[s],a=257*t[n]^16843008*n;f[r]=a<<24|a>>>8,d[r]=a<<16|a>>>16,u[r]=a<<8|a>>>24,p[r]=a;a=16843009*c^65537*s^257*o^16843008*r;_[n]=a<<24|a>>>8,v[n]=a<<16|a>>>16,y[n]=a<<8|a>>>24,g[n]=a,r?(r=o^t[t[t[c^o]]],i^=t[t[i]]):r=i=1}}();var B=[0,1,2,4,8,16,32,64,128,27,54],i=r.AES=e.extend({_doReset:function(){if(!this._nRounds||this._keyPriorReset!==this._key){for(var t=this._keyPriorReset=this._key,e=t.words,r=t.sigBytes/4,i=4*(1+(this._nRounds=6+r)),n=this._keySchedule=[],o=0;o>>24]<<24|h[a>>>16&255]<<16|h[a>>>8&255]<<8|h[255&a]):(a=h[(a=a<<8|a>>>24)>>>24]<<24|h[a>>>16&255]<<16|h[a>>>8&255]<<8|h[255&a],a^=B[o/r|0]<<24),n[o]=n[o-r]^a);for(var s=this._invKeySchedule=[],c=0;c>>24]]^v[h[a>>>16&255]]^y[h[a>>>8&255]]^g[h[255&a]]}}},encryptBlock:function(t,e){this._doCryptBlock(t,e,this._keySchedule,f,d,u,p,h)},decryptBlock:function(t,e){var r=t[e+1];t[e+1]=t[e+3],t[e+3]=r,this._doCryptBlock(t,e,this._invKeySchedule,_,v,y,g,l);r=t[e+1];t[e+1]=t[e+3],t[e+3]=r},_doCryptBlock:function(t,e,r,i,n,o,s,c){for(var a=this._nRounds,h=t[e]^r[0],l=t[e+1]^r[1],f=t[e+2]^r[2],d=t[e+3]^r[3],u=4,p=1;p>>24]^n[l>>>16&255]^o[f>>>8&255]^s[255&d]^r[u++],v=i[l>>>24]^n[f>>>16&255]^o[d>>>8&255]^s[255&h]^r[u++],y=i[f>>>24]^n[d>>>16&255]^o[h>>>8&255]^s[255&l]^r[u++],g=i[d>>>24]^n[h>>>16&255]^o[l>>>8&255]^s[255&f]^r[u++];h=_,l=v,f=y,d=g}_=(c[h>>>24]<<24|c[l>>>16&255]<<16|c[f>>>8&255]<<8|c[255&d])^r[u++],v=(c[l>>>24]<<24|c[f>>>16&255]<<16|c[d>>>8&255]<<8|c[255&h])^r[u++],y=(c[f>>>24]<<24|c[d>>>16&255]<<16|c[h>>>8&255]<<8|c[255&l])^r[u++],g=(c[d>>>24]<<24|c[h>>>16&255]<<16|c[l>>>8&255]<<8|c[255&f])^r[u++];t[e]=_,t[e+1]=v,t[e+2]=y,t[e+3]=g},keySize:8});t.AES=e._createHelper(i)}(),function(){var t=bt,e=t.lib,n=e.WordArray,r=e.BlockCipher,i=t.algo,h=[57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36,63,55,47,39,31,23,15,7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4],l=[14,17,11,24,1,5,3,28,15,6,21,10,23,19,12,4,26,8,16,7,27,20,13,2,41,52,31,37,47,55,30,40,51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32],f=[1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28],d=[{0:8421888,268435456:32768,536870912:8421378,805306368:2,1073741824:512,1342177280:8421890,1610612736:8389122,1879048192:8388608,2147483648:514,2415919104:8389120,2684354560:33280,2952790016:8421376,3221225472:32770,3489660928:8388610,3758096384:0,4026531840:33282,134217728:0,402653184:8421890,671088640:33282,939524096:32768,1207959552:8421888,1476395008:512,1744830464:8421378,2013265920:2,2281701376:8389120,2550136832:33280,2818572288:8421376,3087007744:8389122,3355443200:8388610,3623878656:32770,3892314112:514,4160749568:8388608,1:32768,268435457:2,536870913:8421888,805306369:8388608,1073741825:8421378,1342177281:33280,1610612737:512,1879048193:8389122,2147483649:8421890,2415919105:8421376,2684354561:8388610,2952790017:33282,3221225473:514,3489660929:8389120,3758096385:32770,4026531841:0,134217729:8421890,402653185:8421376,671088641:8388608,939524097:512,1207959553:32768,1476395009:8388610,1744830465:2,2013265921:33282,2281701377:32770,2550136833:8389122,2818572289:514,3087007745:8421888,3355443201:8389120,3623878657:0,3892314113:33280,4160749569:8421378},{0:1074282512,16777216:16384,33554432:524288,50331648:1074266128,67108864:1073741840,83886080:1074282496,100663296:1073758208,117440512:16,134217728:540672,150994944:1073758224,167772160:1073741824,184549376:540688,201326592:524304,218103808:0,234881024:16400,251658240:1074266112,8388608:1073758208,25165824:540688,41943040:16,58720256:1073758224,75497472:1074282512,92274688:1073741824,109051904:524288,125829120:1074266128,142606336:524304,159383552:0,176160768:16384,192937984:1074266112,209715200:1073741840,226492416:540672,243269632:1074282496,260046848:16400,268435456:0,285212672:1074266128,301989888:1073758224,318767104:1074282496,335544320:1074266112,352321536:16,369098752:540688,385875968:16384,402653184:16400,419430400:524288,436207616:524304,452984832:1073741840,469762048:540672,486539264:1073758208,503316480:1073741824,520093696:1074282512,276824064:540688,293601280:524288,310378496:1074266112,327155712:16384,343932928:1073758208,360710144:1074282512,377487360:16,394264576:1073741824,411041792:1074282496,427819008:1073741840,444596224:1073758224,461373440:524304,478150656:0,494927872:16400,511705088:1074266128,528482304:540672},{0:260,1048576:0,2097152:67109120,3145728:65796,4194304:65540,5242880:67108868,6291456:67174660,7340032:67174400,8388608:67108864,9437184:67174656,10485760:65792,11534336:67174404,12582912:67109124,13631488:65536,14680064:4,15728640:256,524288:67174656,1572864:67174404,2621440:0,3670016:67109120,4718592:67108868,5767168:65536,6815744:65540,7864320:260,8912896:4,9961472:256,11010048:67174400,12058624:65796,13107200:65792,14155776:67109124,15204352:67174660,16252928:67108864,16777216:67174656,17825792:65540,18874368:65536,19922944:67109120,20971520:256,22020096:67174660,23068672:67108868,24117248:0,25165824:67109124,26214400:67108864,27262976:4,28311552:65792,29360128:67174400,30408704:260,31457280:65796,32505856:67174404,17301504:67108864,18350080:260,19398656:67174656,20447232:0,21495808:65540,22544384:67109120,23592960:256,24641536:67174404,25690112:65536,26738688:67174660,27787264:65796,28835840:67108868,29884416:67109124,30932992:67174400,31981568:4,33030144:65792},{0:2151682048,65536:2147487808,131072:4198464,196608:2151677952,262144:0,327680:4198400,393216:2147483712,458752:4194368,524288:2147483648,589824:4194304,655360:64,720896:2147487744,786432:2151678016,851968:4160,917504:4096,983040:2151682112,32768:2147487808,98304:64,163840:2151678016,229376:2147487744,294912:4198400,360448:2151682112,425984:0,491520:2151677952,557056:4096,622592:2151682048,688128:4194304,753664:4160,819200:2147483648,884736:4194368,950272:4198464,1015808:2147483712,1048576:4194368,1114112:4198400,1179648:2147483712,1245184:0,1310720:4160,1376256:2151678016,1441792:2151682048,1507328:2147487808,1572864:2151682112,1638400:2147483648,1703936:2151677952,1769472:4198464,1835008:2147487744,1900544:4194304,1966080:64,2031616:4096,1081344:2151677952,1146880:2151682112,1212416:0,1277952:4198400,1343488:4194368,1409024:2147483648,1474560:2147487808,1540096:64,1605632:2147483712,1671168:4096,1736704:2147487744,1802240:2151678016,1867776:4160,1933312:2151682048,1998848:4194304,2064384:4198464},{0:128,4096:17039360,8192:262144,12288:536870912,16384:537133184,20480:16777344,24576:553648256,28672:262272,32768:16777216,36864:537133056,40960:536871040,45056:553910400,49152:553910272,53248:0,57344:17039488,61440:553648128,2048:17039488,6144:553648256,10240:128,14336:17039360,18432:262144,22528:537133184,26624:553910272,30720:536870912,34816:537133056,38912:0,43008:553910400,47104:16777344,51200:536871040,55296:553648128,59392:16777216,63488:262272,65536:262144,69632:128,73728:536870912,77824:553648256,81920:16777344,86016:553910272,90112:537133184,94208:16777216,98304:553910400,102400:553648128,106496:17039360,110592:537133056,114688:262272,118784:536871040,122880:0,126976:17039488,67584:553648256,71680:16777216,75776:17039360,79872:537133184,83968:536870912,88064:17039488,92160:128,96256:553910272,100352:262272,104448:553910400,108544:0,112640:553648128,116736:16777344,120832:262144,124928:537133056,129024:536871040},{0:268435464,256:8192,512:270532608,768:270540808,1024:268443648,1280:2097152,1536:2097160,1792:268435456,2048:0,2304:268443656,2560:2105344,2816:8,3072:270532616,3328:2105352,3584:8200,3840:270540800,128:270532608,384:270540808,640:8,896:2097152,1152:2105352,1408:268435464,1664:268443648,1920:8200,2176:2097160,2432:8192,2688:268443656,2944:270532616,3200:0,3456:270540800,3712:2105344,3968:268435456,4096:268443648,4352:270532616,4608:270540808,4864:8200,5120:2097152,5376:268435456,5632:268435464,5888:2105344,6144:2105352,6400:0,6656:8,6912:270532608,7168:8192,7424:268443656,7680:270540800,7936:2097160,4224:8,4480:2105344,4736:2097152,4992:268435464,5248:268443648,5504:8200,5760:270540808,6016:270532608,6272:270540800,6528:270532616,6784:8192,7040:2105352,7296:2097160,7552:0,7808:268435456,8064:268443656},{0:1048576,16:33555457,32:1024,48:1049601,64:34604033,80:0,96:1,112:34603009,128:33555456,144:1048577,160:33554433,176:34604032,192:34603008,208:1025,224:1049600,240:33554432,8:34603009,24:0,40:33555457,56:34604032,72:1048576,88:33554433,104:33554432,120:1025,136:1049601,152:33555456,168:34603008,184:1048577,200:1024,216:34604033,232:1,248:1049600,256:33554432,272:1048576,288:33555457,304:34603009,320:1048577,336:33555456,352:34604032,368:1049601,384:1025,400:34604033,416:1049600,432:1,448:0,464:34603008,480:33554433,496:1024,264:1049600,280:33555457,296:34603009,312:1,328:33554432,344:1048576,360:1025,376:34604032,392:33554433,408:34603008,424:0,440:34604033,456:1049601,472:1024,488:33555456,504:1048577},{0:134219808,1:131072,2:134217728,3:32,4:131104,5:134350880,6:134350848,7:2048,8:134348800,9:134219776,10:133120,11:134348832,12:2080,13:0,14:134217760,15:133152,2147483648:2048,2147483649:134350880,2147483650:134219808,2147483651:134217728,2147483652:134348800,2147483653:133120,2147483654:133152,2147483655:32,2147483656:134217760,2147483657:2080,2147483658:131104,2147483659:134350848,2147483660:0,2147483661:134348832,2147483662:134219776,2147483663:131072,16:133152,17:134350848,18:32,19:2048,20:134219776,21:134217760,22:134348832,23:131072,24:0,25:131104,26:134348800,27:134219808,28:134350880,29:133120,30:2080,31:134217728,2147483664:131072,2147483665:2048,2147483666:134348832,2147483667:133152,2147483668:32,2147483669:134348800,2147483670:134217728,2147483671:134219808,2147483672:134350880,2147483673:134217760,2147483674:134219776,2147483675:0,2147483676:133120,2147483677:2080,2147483678:131104,2147483679:134350848}],u=[4160749569,528482304,33030144,2064384,129024,8064,504,2147483679],o=i.DES=r.extend({_doReset:function(){for(var t=this._key.words,e=[],r=0;r<56;r++){var i=h[r]-1;e[r]=t[i>>>5]>>>31-i%32&1}for(var n=this._subKeys=[],o=0;o<16;o++){var s=n[o]=[],c=f[o];for(r=0;r<24;r++)s[r/6|0]|=e[(l[r]-1+c)%28]<<31-r%6,s[4+(r/6|0)]|=e[28+(l[r+24]-1+c)%28]<<31-r%6;s[0]=s[0]<<1|s[0]>>>31;for(r=1;r<7;r++)s[r]=s[r]>>>4*(r-1)+3;s[7]=s[7]<<5|s[7]>>>27}var a=this._invSubKeys=[];for(r=0;r<16;r++)a[r]=n[15-r]},encryptBlock:function(t,e){this._doCryptBlock(t,e,this._subKeys)},decryptBlock:function(t,e){this._doCryptBlock(t,e,this._invSubKeys)},_doCryptBlock:function(t,e,r){this._lBlock=t[e],this._rBlock=t[e+1],p.call(this,4,252645135),p.call(this,16,65535),_.call(this,2,858993459),_.call(this,8,16711935),p.call(this,1,1431655765);for(var i=0;i<16;i++){for(var n=r[i],o=this._lBlock,s=this._rBlock,c=0,a=0;a<8;a++)c|=d[a][((s^n[a])&u[a])>>>0];this._lBlock=s,this._rBlock=o^c}var h=this._lBlock;this._lBlock=this._rBlock,this._rBlock=h,p.call(this,1,1431655765),_.call(this,8,16711935),_.call(this,2,858993459),p.call(this,16,65535),p.call(this,4,252645135),t[e]=this._lBlock,t[e+1]=this._rBlock},keySize:2,ivSize:2,blockSize:2});function p(t,e){var r=(this._lBlock>>>t^this._rBlock)&e;this._rBlock^=r,this._lBlock^=r<>>t^this._lBlock)&e;this._lBlock^=r,this._rBlock^=r<192.");var e=t.slice(0,2),r=t.length<4?t.slice(0,2):t.slice(2,4),i=t.length<6?t.slice(0,2):t.slice(4,6);this._des1=o.createEncryptor(n.create(e)),this._des2=o.createEncryptor(n.create(r)),this._des3=o.createEncryptor(n.create(i))},encryptBlock:function(t,e){this._des1.encryptBlock(t,e),this._des2.decryptBlock(t,e),this._des3.encryptBlock(t,e)},decryptBlock:function(t,e){this._des3.decryptBlock(t,e),this._des2.encryptBlock(t,e),this._des1.decryptBlock(t,e)},keySize:6,ivSize:2,blockSize:2});t.TripleDES=r._createHelper(s)}(),function(){var t=bt,e=t.lib.StreamCipher,r=t.algo,i=r.RC4=e.extend({_doReset:function(){for(var t=this._key,e=t.words,r=t.sigBytes,i=this._S=[],n=0;n<256;n++)i[n]=n;n=0;for(var o=0;n<256;n++){var s=n%r,c=e[s>>>2]>>>24-s%4*8&255;o=(o+i[n]+c)%256;var a=i[n];i[n]=i[o],i[o]=a}this._i=this._j=0},_doProcessBlock:function(t,e){t[e]^=n.call(this)},keySize:8,ivSize:0});function n(){for(var t=this._S,e=this._i,r=this._j,i=0,n=0;n<4;n++){r=(r+t[e=(e+1)%256])%256;var o=t[e];t[e]=t[r],t[r]=o,i|=t[(t[e]+t[r])%256]<<24-8*n}return this._i=e,this._j=r,i}t.RC4=e._createHelper(i);var o=r.RC4Drop=i.extend({cfg:i.cfg.extend({drop:192}),_doReset:function(){i._doReset.call(this);for(var t=this.cfg.drop;0>>24)|4278255360&(t[r]<<24|t[r]>>>8);var i=this._X=[t[0],t[3]<<16|t[2]>>>16,t[1],t[0]<<16|t[3]>>>16,t[2],t[1]<<16|t[0]>>>16,t[3],t[2]<<16|t[1]>>>16],n=this._C=[t[2]<<16|t[2]>>>16,4294901760&t[0]|65535&t[1],t[3]<<16|t[3]>>>16,4294901760&t[1]|65535&t[2],t[0]<<16|t[0]>>>16,4294901760&t[2]|65535&t[3],t[1]<<16|t[1]>>>16,4294901760&t[3]|65535&t[0]];for(r=this._b=0;r<4;r++)Rt.call(this);for(r=0;r<8;r++)n[r]^=i[r+4&7];if(e){var o=e.words,s=o[0],c=o[1],a=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),h=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8),l=a>>>16|4294901760&h,f=h<<16|65535&a;n[0]^=a,n[1]^=l,n[2]^=h,n[3]^=f,n[4]^=a,n[5]^=l,n[6]^=h,n[7]^=f;for(r=0;r<4;r++)Rt.call(this)}},_doProcessBlock:function(t,e){var r=this._X;Rt.call(this),lt[0]=r[0]^r[5]>>>16^r[3]<<16,lt[1]=r[2]^r[7]>>>16^r[5]<<16,lt[2]=r[4]^r[1]>>>16^r[7]<<16,lt[3]=r[6]^r[3]>>>16^r[1]<<16;for(var i=0;i<4;i++)lt[i]=16711935&(lt[i]<<8|lt[i]>>>24)|4278255360&(lt[i]<<24|lt[i]>>>8),t[e+i]^=lt[i]},blockSize:4,ivSize:2}),ct.Rabbit=at._createHelper(ut),bt.mode.CTR=(pt=bt.lib.BlockCipherMode.extend(),_t=pt.Encryptor=pt.extend({processBlock:function(t,e){var r=this._cipher,i=r.blockSize,n=this._iv,o=this._counter;n&&(o=this._counter=n.slice(0),this._iv=void 0);var s=o.slice(0);r.encryptBlock(s,0),o[i-1]=o[i-1]+1|0;for(var c=0;c>>16,t[1],t[0]<<16|t[3]>>>16,t[2],t[1]<<16|t[0]>>>16,t[3],t[2]<<16|t[1]>>>16],i=this._C=[t[2]<<16|t[2]>>>16,4294901760&t[0]|65535&t[1],t[3]<<16|t[3]>>>16,4294901760&t[1]|65535&t[2],t[0]<<16|t[0]>>>16,4294901760&t[2]|65535&t[3],t[1]<<16|t[1]>>>16,4294901760&t[3]|65535&t[0]],n=this._b=0;n<4;n++)Mt.call(this);for(n=0;n<8;n++)i[n]^=r[n+4&7];if(e){var o=e.words,s=o[0],c=o[1],a=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),h=16711935&(c<<8|c>>>24)|4278255360&(c<<24|c>>>8),l=a>>>16|4294901760&h,f=h<<16|65535&a;i[0]^=a,i[1]^=l,i[2]^=h,i[3]^=f,i[4]^=a,i[5]^=l,i[6]^=h,i[7]^=f;for(n=0;n<4;n++)Mt.call(this)}},_doProcessBlock:function(t,e){var r=this._X;Mt.call(this),Bt[0]=r[0]^r[5]>>>16^r[3]<<16,Bt[1]=r[2]^r[7]>>>16^r[5]<<16,Bt[2]=r[4]^r[1]>>>16^r[7]<<16,Bt[3]=r[6]^r[3]>>>16^r[1]<<16;for(var i=0;i<4;i++)Bt[i]=16711935&(Bt[i]<<8|Bt[i]>>>24)|4278255360&(Bt[i]<<24|Bt[i]>>>8),t[e+i]^=Bt[i]},blockSize:4,ivSize:2}),vt.RabbitLegacy=yt._createHelper(St),bt.pad.ZeroPadding={pad:function(t,e){var r=4*e;t.clamp(),t.sigBytes+=r-(t.sigBytes%r||r)},unpad:function(t){var e=t.words,r=t.sigBytes-1;for(r=t.sigBytes-1;0<=r;r--)if(e[r>>>2]>>>24-r%4*8&255){t.sigBytes=r+1;break}}},bt}); --------------------------------------------------------------------------------