ChatGPT Άπειρο ∞

Δημιουργήστε ατελείωτες απαντήσεις από το γνώστη ChatGPT (σε οποιαδήποτε γλώσσα!)

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name                ChatGPT Infinity ∞
// @name:af             ChatGPT Oneindig ∞
// @name:ar             دردشةGPT إنفينيتي ∞
// @name:az             ChatGPT Sonsuzluq ∞
// @name:be             ChatGPT Бясконцасць ∞
// @name:bg             ChatGPT Безкрайност ∞
// @name:bn             ChatGPT ইনফিনিটি ∞
// @name:bo             ChatGPT དག་སྐྱེས་ཡོད་པ་ ∞
// @name:bs             ChatGPT Beskrajnost ∞
// @name:ca             ChatGPT Infinit ∞
// @name:ckb            ChatGPT نەپێندییە ∞
// @name:cs             ChatGPT Nekonečno ∞
// @name:cy             ChatGPT Anfeidredd ∞
// @name:da             ChatGPT Uendelighed ∞
// @name:de             ChatGPT Unendlichkeit ∞
// @name:dv             ChatGPT ނުވަތަ ބާވައްޖޭގެން ∞
// @name:dz             ChatGPT རྩེད་སྒྲིབ་གཉིས་ ∞
// @name:el             ChatGPT Άπειρο ∞
// @name:eo             ChatGPT Infinito ∞
// @name:es             ChatGPT Infinito ∞
// @name:et             ChatGPT Lõpmatus ∞
// @name:eu             ChatGPT Infinitua ∞
// @name:fa             ChatGPT بینهایت ∞
// @name:fi             ChatGPT Ääretön ∞
// @name:fo             ChatGPT Óendanlighed ∞
// @name:fr             ChatGPT Infini ∞
// @name:fr-CA          ChatGPT Infini ∞
// @name:gl             ChatGPT Infinito ∞
// @name:gu             ChatGPT અનંત ∞
// @name:haw            ChatGPT Māhina ʻole ∞
// @name:he             ChatGPT אינסוף ∞
// @name:hi             ChatGPT अनंत ∞
// @name:hr             ChatGPT Beskrajnost ∞
// @name:hu             ChatGPT Végtelenség ∞
// @name:hy             ChatGPT Անվերջ ∞
// @name:id             ChatGPT Infinity ∞
// @name:is             ChatGPT Óendanleiki ∞
// @name:it             ChatGPT Infinito ∞
// @name:ja             ChatGPT 無限 ∞
// @name:ka             ChatGPT უსასრულობა ∞
// @name:km             ChatGPT អនឡាញ ∞
// @name:kn             ChatGPT ಅನಂತ ∞
// @name:ko             ChatGPT 무한 ∞
// @name:ku             ChatGPT Pêşangeh ∞
// @name:ky             ChatGPT Ички ∞
// @name:la             ChatGPT Infinitas ∞
// @name:lb             ChatGPT Unendlechkeet ∞
// @name:lo             ChatGPT ບໍ່ໄປສູ່ຈັກຂອງສາມຫວ່າງ ∞
// @name:lt             ChatGPT Begalybė ∞
// @name:lv             ChatGPT Bezgalība ∞
// @name:mk             ChatGPT Бесконечност ∞
// @name:ml             ChatGPT അനന്തത ∞
// @name:mn             ChatGPT Тэгш бус ∞
// @name:mt             ChatGPT Infinità ∞
// @name:my             ChatGPT မြင်ကွင်း ∞
// @name:ne             ChatGPT अनंत ∞
// @name:nl             ChatGPT Oneindigheid ∞
// @name:no             ChatGPT Uendelighet ∞
// @name:pa             ChatGPT ਇਨਫਿਨਿਟੀ ∞
// @name:pl             ChatGPT Nieskończoność ∞
// @name:ps             ChatGPT لامکان ∞
// @name:pt             ChatGPT Infinito ∞
// @name:pt-BR          ChatGPT Infinito ∞
// @name:ro             ChatGPT Infinitate ∞
// @name:ru             ChatGPT Бесконечность ∞
// @name:si             ChatGPT අනන්තය ∞
// @name:sk             ChatGPT Nekonečno ∞
// @name:sl             ChatGPT Neskončnost ∞
// @name:so             ChatGPT Qaybtiisa ∞
// @name:sr             ChatGPT Бескрајност ∞
// @name:sv             ChatGPT Oändlighet ∞
// @name:ta             ChatGPT முடிவிலிருந்து ∞
// @name:te             ChatGPT అనంతత ∞
// @name:tg             ChatGPT Беоҳӣ ∞
// @name:th             ChatGPT อนันต์ ∞
// @name:ti             ChatGPT መደመር ∞
// @name:tk             ChatGPT Sonsuzluk ∞
// @name:tr             ChatGPT Sonsuzluk ∞
// @name:uk             ChatGPT Нескінченність ∞
// @name:ur             ChatGPT بے انتہا ∞
// @name:vi             ChatGPT Vô cùng ∞
// @name:yi             ChatGPT אינפיניטי ∞
// @name:zh             ChatGPT 无限 ∞
// @name:zh-CN          ChatGPT 无限 ∞
// @name:zh-HK          ChatGPT 無限 ∞
// @name:zh-SG          ChatGPT 无限 ∞
// @name:zh-TW          ChatGPT 無限 ∞
// @description         Generate endless answers from all-knowing ChatGPT (in any language!)
// @description:af      Genereer eindelose antwoorde van die alwetende ChatGPT (in enige taal!)
// @description:am      ሓበሬታይ ኣይነበርና መልእኽቲ ኣለኹም ኣሎኻዊ ያልኣይት ChatGPT (በቋንቋ!)
// @description:ar      قم بتوليد إجابات لا نهائية من ChatGPT المعرف بكل شيء (بأي لغة!)
// @description:az      Hər şeyi bilən ChatGPT-dən sonsuz cavablar yaradın (hər hansı bir dil ilə!)
// @description:be      Стварыце бясконцы адказы ад ўсеведучага ChatGPT (на любой мове!)
// @description:bem     Pamene mwaposa mafolosho a mʌnoze ChatGPT (mu lupiya lwa ndalama!)
// @description:bg      Генерирайте безкрайни отговори от всезнайния ChatGPT (на всяк език!)
// @description:bn      সর্বজ্ঞ চ্যাটজিপিটি থেকে অসীম উত্তর তৈরি করুন (যে কোন ভাষায়!)
// @description:bo      བཟོས་པ་བརྗོད་པའི་ChatGPTགི་གྲོས་པར་འགྲུབ་འདེམས་བསྐྱེད་མི་འོངས་པ། (ལས་སྐབས་ཀྱི་སྐད་ཡིག་གི་སྐད་!)
// @description:bs      Generišite beskonačne odgovore od sveznajućeg ChatGPT (na bilo kom jeziku!)
// @description:ca      Genereu respostes infinites des de l'omniscient ChatGPT (en qualsevol idioma!)
// @description:ceb     Sukdagon ang walay katapusan nga mga tubag gikan sa tanan-mahibaw-anong ChatGPT (sa bisan unsang pinulongan!)
// @description:ckb     پێشبینی چاتگپتەکە دیارییەکانی پێکراوەکان بنووسە (بە هەر زمانێکی دیکە!)
// @description:cs      Generujte nekonečné odpovědi od vševědoucího ChatGPT (v jakémkoli jazyce!)
// @description:cy      Cynhyrchwch atebion diddiwedd o ChatGPT y gŵr sy'n gwybod popeth (mewn unrhyw iaith!)
// @description:da      Generer endeløse svar fra den altvidende ChatGPT (på hvilket som helst sprog!)
// @description:de      Generieren Sie endlose Antworten von dem allwissenden ChatGPT (in beliebiger Sprache!)
// @description:dv      އެހެނދުކަޗެއްވެސީ ޗެއްސިސްޓޯނަށް ނިޔަލައިފައިވަނީ ސުރުކޮށް ފީހުން (ކަންއެވެސް ހަމަވެސް!)
// @description:dz      ཆགས་ཀྱིས་ལ་བརྟེན་གང་རུང་གི་ChatGPTགི་ཚོགས་པའི་སྐད་ཡིག་གྱི་སྐད་ཡིག་བྱེད་པ། (བླ་མའི་སྐད་ཡིག་!)
// @description:el      Δημιουργήστε ατελείωτες απαντήσεις από το γνώστη ChatGPT (σε οποιαδήποτε γλώσσα!)
// @description:eo      Kreu nesfinaĵajn respondojn el la ĉio-scianta ChatGPT (en ajn lingvo!)
// @description:es      Genera respuestas infinitas desde el ChatGPT omnisciente (¡en cualquier idioma!)
// @description:et      Loo lõputuid vastuseid kõike-teadvast ChatGPT-st (mis tahes keeles!)
// @description:eu      Sortu erantzun infinituak guztiz-arduratsuaren ChatGPT-tik (edozein hizkuntzan!)
// @description:fa      پاسخهای بیپایانی را از ChatGPT همهدانا تولید کنید (به هر زبانی!)
// @description:fi      Luo loputtomia vastauksia kaikkitietävästä ChatGPT:stä (millä tahansa kielellä!)
// @description:fo      Skapa endalaus svør frá altvitandi ChatGPT (á hvørjum málrøð!)
// @description:fr      Générez des réponses infinies à partir de ChatGPT qui sait tout (dans n'importe quelle langue!)
// @description:fr-CA   Générez des réponses infinies à partir de ChatGPT qui sait tout (dans n'importe quelle langue!)
// @description:gd      Cruthaich freagairtean gun crìoch à ChatGPT a tha a' faighneachd gach càil (ann an sam bith cànan!)
// @description:gl      Xere as respostas infinitas do ChatGPT que todo o sabe (en calquera lingua!)
// @description:gu      જ્ઞાનવાન ChatGPT થી અનંત જવાબો ઉત્પન કરો (કોઈ પણ ભાષામાં!)
// @description:haw     Haleleʻa i nā ʻōlelo pālulelo mai ke kupa ʻike loa o ChatGPT (i loko o kēlā ʻōlelo aku aʻe!)
// @description:he      יצרו תשובות אינסופיות מה-ChatGPT המבין הכל (בכל שפה!)
// @description:hi      सभी-जाननेवाले चैटजीपीटी से अनंत उत्तरों का उत्पादन करें (किसी भी भाषा में!)
// @description:hr      Generirajte beskrajne odgovore iz sveznajućeg ChatGPT-a (na bilo kojem jeziku!)
// @description:ht      Jenere repons san fen soti nan ChatGPT k-ap konnen tout bagay yo (nan nenpòt lang!)
// @description:hu      Végtelen válaszokat generáljon a mindentudó ChatGPT-ből (bármely nyelven!)
// @description:hy      Ստեղծեք անսահմանափակ պատասխաններ ամենագիտական ChatGPT-ից (ցանկացած լեզուն մեջ!)
// @description:id      Hasilkan jawaban tak terbatas dari ChatGPT yang tahu segalanya (dalam bahasa apa pun!)
// @description:is      Búið til endalaus svör frá allvissu ChatGPT (á hvaða tungumáli sem er!)
// @description:it      Genera risposte infinite dall'onnisciente ChatGPT (in qualsiasi lingua!)
// @description:ja      あらゆる言語で全知のChatGPTから無限の回答を生成します!
// @description:jv      Mbukak panggung jawaban saka ChatGPT kang suwénéh kabèh (kénging basa apapun!)
// @description:ka      შექმენით უსასრულო პასუხები ყველგანაწილებული ChatGPT-დან (ნელა ენაზე!)
// @description:kab     Kkes-as yidir seg yisem-asen n tafriqt ara ddunnit ChatGPT (di tifrat ara ddunit!)
// @description:kk      Барлық тілде бар білген ChatGPT-ден шексіз жауаптар жасау (қандай да тілде!)
// @description:km      បង្កើតចម្លើយមិនឃើញចប់ពី ChatGPT ដែលចែកសង្ស័យទាំងអស់ (ជាន់គ្រប់ភាសា!)
// @description:kn      ಎಲ್ಲರು ತಿಳಿದಿರುವ ಚಾಟ್ಜಿಪಿಟಿಯಿಂದ ಅನಂತ ಉತ್ತರಗಳನ್ನು ರಚಿಸಿ (ಯಾವುದೇ ಭಾಷೆಯಲ್ಲಿ!)
// @description:ko      어떤 언어로든지 무궁무진한 답변을 만들어내는 ChatGPT입니다!
// @description:ku      Ji ChatGPT-ê, ku hemî tiştan dizane, bersiva li serbazên li dor qewî yên hilbijartin (bi hertiştî zimanek!)
// @description:ky      Түз билимдүү ChatGPT боюнча чыгармаларды жаса
// @description:la      Genera infinitas responsiones de ChatGPT omniscio (in qualibet lingua!)
// @description:lb      Generéiert endlos Äntwerten vum allwëssende ChatGPT (op jiddere Sprooch!)
// @description:lo      ສ້າງຜົນສົດທີ່ສາມາດເລືອກຈາກພາສາທີ່ຮູ້ບຸກກຳລັງ ChatGPT (ໃນພາສາໃດໜຶ່ງ!)
// @description:lt      Sugeneruokite begalinį atsakymų kiekį iš visai žinoančio ChatGPT (bet kuria kalba!)
// @description:lv      Ģenerē nebeidzamus atbilžu variantus no vissapratīgā ChatGPT (jebkurā valodā!)
// @description:mg      Mandoza ny valiny miaraka amin'ny ChatGPT mahalala ny zavatra rehetra (amin'ny fiteny iray kokoa!)
// @description:mi      Whakapūmau i ngā whakautu kore mutunga mai i te ChatGPT matau i ngā reo katoa!
// @description:mk      Генерирајте безброј одговори од сèзнаената ChatGPT (на било кој јазик!)
// @description:ml      എന്നെഴുതാൻ അനന്യനായ ChatGPT (ഏതെങ്കിലും ഭാഷയിൽ) ഇന്നേക്കും വേണ്ടി അവസാനിപ്പിക്കുക!
// @description:mn      Сүүлд үлдсэнээсээ хайрцаг болох ChatGPT (ямар ч хэл дээр) дээрхээр ярих
// @description:ms      Cipta pelbagai jawapan daripada ChatGPT yang tahu segala-galanya (dalam apa-apa bahasa!)
// @description:mt      Iġġenera risposti infiniti mill-ChatGPT li kollha jaf (f'xi lingwa!)
// @description:my      အားလုံးကိုသင်ရိုးရိုးဆွဲနိုင်သည့် ChatGPT (တစ်ခုမှာယူသုံးရန်!)
// @description:ne      सबै-ज्ञानी ChatGPT बाट अनंत उत्तरहरू उत्पन्न गर्नुहोस् (कुनै पनि भाषामा!)
// @description:nl      Genereer eindeloze antwoorden van alwetende ChatGPT (in elke taal!)
// @description:no      Generer endeløse svar fra allvitende ChatGPT (på hvilket som helst språk!)
// @description:ny      Galimoto mabwino a mtendere zosiyanasiyana kuchokera ku ChatGPT woyankhula zonse! (muyankhulitsa chilichonse!)
// @description:pa      ਸਭ ਜਾਣ ਵਾਲੇ ChatGPT ਤੋਂ ਲੰਬੇ ਉੱਤਰਾਂ ਨੂੰ ਬਣਾਓ (ਕਿਸੇ ਵੀ ਭਾਸ਼ਾ ਵਿੱਚ!)
// @description:pap     Hasi respuesta sinfin di ChatGPT ku tur sabi (na kua idioma!)
// @description:pl      Generuj nieskończone odpowiedzi od wszechwiedzącego ChatGPT (w dowolnym języku!)
// @description:ps      د هغوی چټکال ChatGPT لخوا نهایت جوابونه جوړه کړئ (د هر یوه ژبه کی!)
// @description:pt      Gere respostas infinitas do ChatGPT onisciente (em qualquer idioma!)
// @description:pt-BR   Gere respostas infinitas do ChatGPT onisciente (em qualquer idioma!)
// @description:rn      Basha inzira nk'itandukanye z'uko ChatGPT uzi (mu rurimi rwose!)
// @description:ro      Generează răspunsuri infinite de la ChatGPT omniscient (în orice limbă!)
// @description:ru      Генерируйте бесконечные ответы от всезнающего ChatGPT (на любом языке!)
// @description:rw      Banda inama z'imirimo isigaye zose z'umuco wa ChatGPT (mu rurimi rwose!)
// @description:sg      Tia ngamana nga mbetela ti ChatGPT tozuwa mitayi mingi (po wundi ndimi yo ngambo!)
// @description:si      සියළු දැනටමත් සහතිකපත්කරන තවත් සිතියම් සැකසුම් ලබා දෙන්නාවූ ChatGPT සෑදීම (ඕනෑම භාෂාවෙන්ම!)
// @description:sk      Generujte nekonečné odpovede od vševietajúceho ChatGPT (v akomkoľvek jazyku!)
// @description:sl      Generirajte neskončne odgovore iz vsevednega ChatGPT (v katerem koli jeziku!)
// @description:sm      Faia se faiga tele i le ChatGPT eseese (i nisi gagana!)
// @description:sn      Simudza mhinduro dzakawanda kubva kune ChatGPT ichiwanikwa chisarudzo! (mune rimwe nguva!)
// @description:so      Kor u qaado jawaabo kala duwan oo ka soo saar ChatGPT (luuqad ka mid ah!)
// @description:sr      Генеришите безброј одговора од свемоћног ChatGPT (на било ком језику!)
// @description:sv      Generera oändliga svar från allvetande ChatGPT (på valfritt språk!)
// @description:sw      Toa majibu yasiyokuwa na mwisho kutoka kwa ChatGPT mwenye maarifa yote (katika lugha yoyote!)
// @description:ta      அனைத்து தகவலையும் அறியப்பட்ட சொந்தமான ChatGPT இலிருந்து முடிவுகளை உருவாக்கவும் (எந்த மொழியிலும்!)
// @description:te      అన్నింటినీకింట మాటలు రాయండి ChatGPT గురించి అనేక జవాబాలను సృష్టించండి (ఏదైనా భాషలో!)
// @description:tg      Ҷавобҳои бесуданни ChatGPTи ҳамаифақат (дар як забони муайяни!)
// @description:th      สร้างคำตอบไม่สิ้นสุดจาก ChatGPT ที่รู้ทุกสิ่ง (ในภาษาใดก็ได้!)
// @description:ti      ክርስትን ለማውጣት ከገጽታውን ChatGPT የተከሳሽ አስተካክል አስተካክሎት (በእውነት ቋንቋ!)
// @description:tk      Şeýle anlaşylýan ChatGPT (her hili üçin) arasyndan bäşmüňhat jawaplar döret
// @description:tn      Hlela zitsha zwine zwiṱhiselela kha ChatGPT vhufudziṱe (muvhili wo vha u ite!)
// @description:to      Fakatonutonu ʻihe ngāuekesi mei he ChatGPT fakaongoongo toenga (i he lea faka-Tonga ia!)
// @description:tpi     Sanapim hamamasples long save olsem ChatGPT i masples (long wanpela tok ples!)
// @description:tr      Bilge ChatGPT'den sonsuz cevaplar üret (herhangi bir dilde!)
// @description:uk      Генеруйте безкінечні відповіді від усезнаючого ChatGPT (на будь-якій мові!)
// @description:ur      سب جاننے والے ChatGPT سے لامتناہی جوابات پیدا کریں (کسی بھی زبان میں!)
// @description:uz      Barcha biladigan ChatGPT dan cheklovli javoblar oling (hech qanday tilda ham)!
// @description:vi      Tạo ra vô số câu trả lời từ ChatGPT thông minh (bằng bất kỳ ngôn ngữ nào!)
// @description:xh      Bhala izinto ezingekwaziyo eziyimfihlo kusuka ku ChatGPT (ngolwimi lwanyanetha!)
// @description:yi      דזשענערייט סאָף ענטפֿערס פֿון אַלע-געוויסן ChatGPT (אין קיין שפּראַך!)
// @description:zh      从无所不知的 ChatGPT 生成无穷无尽的答案 (用任何语言!)
// @description:zh-CN   从无所不知的 ChatGPT 生成无穷无尽的答案 (用任何语言!)
// @description:zh-HK   從無所不知的 ChatGPT 生成無窮無盡的答案 (用任何語言!)
// @description:zh-SG   从无所不知的 ChatGPT 生成无穷无尽的答案 (用任何语言!)
// @description:zh-TW   從無所不知的 ChatGPT 生成無窮無盡的答案 (用任何語言!)
// @author              Adam Lui
// @namespace           https://github.com/adamlui
// @version             2024.12.21.12
// @license             MIT
// @icon                https://media.chatgptinfinity.com/images/icons/infinity-symbol/circled/with-robot/icon48.png?f196818
// @icon64              https://media.chatgptinfinity.com/images/icons/infinity-symbol/circled/with-robot/icon64.png?f196818
// @compatible          chrome
// @compatible          firefox
// @compatible          edge
// @compatible          opera
// @compatible          brave
// @compatible          vivaldi
// @compatible          waterfox
// @compatible          librewolf
// @compatible          ghost
// @compatible          qq
// @compatible          whale
// @compatible          kiwi
// @match               *://chatgpt.com/*
// @match               *://chat.openai.com/*
// @connect             cdn.jsdelivr.net
// @connect             update.greatest.deepsurf.us
// @require             https://cdn.jsdelivr.net/npm/@kudoai/[email protected]/dist/chatgpt.min.js#sha256-LfB3mqeB6Xiq2BDub1tn3BtvEiMcaWEp+I094MFpA+Q=
// @require             https://cdn.jsdelivr.net/gh/adamlui/chatgpt-infinity@cab88ecb787f8354800fa30649132db1ee2e591e/chrome/extension/components/modals.js#sha256-6eTSUF5YPmISKcTY7BKPV5cdg2hFB/3afF28gol95Rw=
// @require             https://cdn.jsdelivr.net/gh/adamlui/chatgpt-infinity@18a073638eb709af491d308bf4e28f82d7158740/chrome/extension/components/toggles.js#sha256-mwqlbhGOHYUwevb4IKq9gfPqEtDpyGk/1Nz6QfP+4FA=
// @require             https://cdn.jsdelivr.net/gh/adamlui/chatgpt-infinity@8dcd26ab5d84ba50229f4e0e37deb28e4a3435a3/chrome/extension/lib/dom.js#sha256-kNvqFW2SkhKh6oBwkfKyJbjNAped4c1mF3uSQhkUWjI=
// @require             https://cdn.jsdelivr.net/gh/adamlui/chatgpt-infinity@704858dafc0915cb67367ea949e6997408aaa29c/chrome/extension/lib/settings.js#sha256-xuu3HlQPLCQLCjRi2noGBdcpCZkt38L8jGhM2EvPSGE=
// @resource brsCSS     https://assets.aiwebextensions.com/styles/rising-stars/dist/black.min.css?v=0cde30f9ae3ce99ae998141f6e7a36de9b0cc2e7#sha256-4nbm81/JSas4wmxFIdliBBzoEEHRZ057TpzNX1PoQIs=
// @resource wrsCSS     https://assets.aiwebextensions.com/styles/rising-stars/dist/white.min.css?v=0cde30f9ae3ce99ae998141f6e7a36de9b0cc2e7#sha256-pW8xWWV6tm8Q6Ms+HWZv6+QzzTLJPyL1DyE18ywpVaE=
// @grant               GM_setValue
// @grant               GM_getValue
// @grant               GM_registerMenuCommand
// @grant               GM_unregisterMenuCommand
// @grant               GM_getResourceText
// @grant               GM_xmlhttpRequest
// @grant               GM.xmlHttpRequest
// @noframes
// @homepageURL         https://www.chatgptinfinity.com
// @supportURL          https://support.chatgptinfinity.com
// @contributionURL     https://github.com/sponsors/adamlui
// ==/UserScript==

// Documentation: https://docs.chatgptinfinity.com
// NOTE: This script relies on the powerful chatgpt.js library @ https://chatgpt.js.org
//  © 2023–2024 KudoAI & contributors under the MIT license.

(async () => {

    // Init ENV context
    const env = {
        browser: {
            language: chatgpt.getUserLanguage(), isFF: chatgpt.browser.isFirefox(), isMobile: chatgpt.browser.isMobile()
        },
        scriptManager: {
            name: (() => { try { return GM_info.scriptHandler } catch (err) { return 'unknown' }})(),
            version: (() => { try { return GM_info.version } catch (err) { return 'unknown' }})()
        },
        scheme: getScheme()
    }
    env.browser.isPortrait = env.browser.isMobile && (window.innerWidth < window.innerHeight)
    const xhr = typeof GM != 'undefined' && GM.xmlHttpRequest || GM_xmlhttpRequest

    // Init APP data
    const app = {
        version: GM_info.script.version, configKeyPrefix: 'chatGPTinfinity',
        chatgptJSver: /chatgpt\.js@([\d.]+)/.exec(GM_info.scriptMetaStr)[1], urls: {},
        latestAssetCommitHash: '17856df' // for cached app.json + messages.json + navicon in toggles.sidebar.insert()
    }
    app.urls.assetHost = `https://cdn.jsdelivr.net/gh/adamlui/chatgpt-infinity@${app.latestAssetCommitHash}`
    const remoteAppData = await new Promise(resolve => xhr({
        method: 'GET', url: `${app.urls.assetHost}/app.json`, onload: resp => resolve(JSON.parse(resp.responseText)) }))
    Object.assign(app, { ...remoteAppData, urls: { ...app.urls, ...remoteAppData.urls }})
    app.urls.update = app.urls.greasyFork.replace('https://', 'https://update.')
        .replace(/(\d+)-?([a-z-]*)$/i, (_, id, name) => `${id}/${ name || 'script' }.meta.js`)
    app.msgs = {
        appName: app.name,
        appAuthor: app.author.name,
        appDesc: 'Generate endless answers from all-knowing ChatGPT (in any language!)',
        menuLabel_infinityMode: 'אוטו-תגובה',
        menuLabel_autoStart: 'Auto-Start',
        menuLabel_toggleVis: 'Toggle Visibility',
        menuLabel_autoScroll: 'Auto-Scroll',
        menuLabel_replyLang: 'Reply Language',
        menuLabel_replyTopic: 'Reply Topic',
        menuLabel_all: 'ALL',
        menuLabel_replyInt: 'Reply Interval',
        menuLabel_about: 'About',
        menuLabel_donate: 'Please send a donation',
        menuLabel_disabled: 'Disabled (extension installed)',
        about_version: 'Version',
        about_poweredBy: 'Powered by',
        about_openSourceCode: 'Open source code',
        prompt_updateReplyLang: 'Update reply language',
        prompt_updateReplyTopic: 'Update reply topic',
        prompt_orEnter: 'or enter',
        prompt_updateReplyInt: 'Update reply interval (minimum 5 secs)',
        helptip_autoStart: 'Automatically start Infinity Mode when visiting chatgpt.com',
        helptip_toggleVis: 'Show Infinity Mode toggle in sidebar',
        helptip_autoScroll: 'Automatically scroll to bottom as replies are generating',
        alert_replyLangUpdated: 'Language updated',
        alert_willReplyIn: 'will reply in',
        alert_yourSysLang: 'your system language',
        alert_replyTopicUpdated: 'Topic updated',
        alert_willAnswer: 'will answer questions',
        alert_onTopicOf: 'on the topic of',
        alert_onAllTopics: 'on ALL topics',
        alert_replyIntUpdated: 'Interval updated',
        alert_willReplyEvery: 'will reply every',
        alert_choosePlatform: 'Choose a platform',
        alert_updateAvail: 'Update available',
        alert_newerVer: 'An update to',
        alert_isAvail: 'is available',
        alert_upToDate: 'Up-to-date',
        alert_isUpToDate: 'is up-to-date',
        alert_showYourSupport: 'Show your support',
        alert_isOSS: 'is open-source software built & maintained for free through 100% volunteer efforts',
        alert_despiteAffliction: 'Despite being severely afflicted by',
        alert_longCOVID: 'long COVID',
        alert_since2020: 'since 2020',
        alert_byDonatingResults: 'by donating, you help me to continue improving, fixing bugs, adding new features, and making the software even better',
        alert_yourContrib: 'Your contribution',
        alert_noMatterSize: 'no matter the size',
        alert_directlySupports: 'directly supports my unpaid efforts to ensure this project remains free and open for all to use',
        alert_tyForSupport: 'Thank you for your support',
        alert_author: 'author',
        btnLabel_moreAIextensions: 'More AI Extensions',
        btnLabel_rateUs: 'Rate Us',
        btnLabel_getSupport: 'Get Support',
        btnLabel_checkForUpdates: 'Check for Updates',
        btnLabel_update: 'Update',
        btnLabel_dismiss: 'Dismiss',
        link_viewChanges: 'View changes',
        unit_seconds: 'seconds',
        state_enabled: 'פועלת',
        state_disabled: 'לא פועלת',
        state_on: 'on',
        state_off: 'off'
    }

    // LOCALIZE app.msgs for non-English users
    if (!env.browser.language.startsWith('en')) {
        const localizedMsgs = await new Promise(resolve => {
            const msgHostDir = app.urls.assetHost + '/chrome/extension/_locales/',
                  msgLocaleDir = ( env.browser.language ? env.browser.language.replace('-', '_') : 'en' ) + '/'
            let msgHref = msgHostDir + msgLocaleDir + 'messages.json', msgXHRtries = 0
            function fetchMsgs() { xhr({ method: 'GET', url: msgHref, onload: handleMsgs })}
            function handleMsgs(resp) {
                try { // to return localized messages.json
                    const msgs = JSON.parse(resp.responseText), flatMsgs = {}
                    for (const key in msgs)  // remove need to ref nested keys
                        if (typeof msgs[key] == 'object' && 'message' in msgs[key])
                            flatMsgs[key] = msgs[key].message
                    resolve(flatMsgs)
                } catch (err) { // if bad response
                    msgXHRtries++ ; if (msgXHRtries == 3) return resolve({}) // try original/region-stripped/EN only
                    msgHref = env.browser.language.includes('-') && msgXHRtries == 1 ? // if regional lang on 1st try...
                        msgHref.replace(/([^_]+_[^_]+)_[^/]*(\/.*)/, '$1$2') // ...strip region before retrying
                            : ( msgHostDir + 'en/messages.json' ) // else use default English messages
                    fetchMsgs()
                }
            }
            fetchMsgs()
        })
        Object.assign(app.msgs, localizedMsgs)
    }

    // Export DEPENDENCIES to imported resources
    dom.dependencies.import({ env }) // for env.scheme
    modals.dependencies.import({ app, env, updateCheck }) // for app data + env.scheme + update callback in modals.about
    settings.dependencies.import({ app }) // for app.msgs + app.configKeyPrefix refs

    // Init SETTINGS
    settings.load(Object.keys(settings.controls).filter(key => key != 'infinityMode')) // exclude infinityMode...
    settings.save('infinityMode', false) // ...to always init as false
    if (!config.replyLanguage) settings.save('replyLanguage', env.browser.language) // init reply language if unset
    if (!config.replyTopic) settings.save('replyTopic', app.msgs.menuLabel_all) // init reply topic if unset
    if (!config.replyInterval) settings.save('replyInterval', 7) // init refresh interval to 7 secs if unset

    // Define MENU functions

    const menu = {
        ids: [], state: {
            symbols: ['❌', '✔️'], separator: env.scriptManager.name == 'Tampermonkey' ? ' — ' : ': ',
            words: [app.msgs.state_off.toUpperCase(), app.msgs.state_on.toUpperCase()]
        },

        register() {
            const tooltipsSupported = env.scriptManager.name == 'Tampermonkey'
                                   && parseInt(env.scriptManager.version.split('.')[0]) >= 5

            // Show "Disabled (extension installed)"
            if (env.extensionInstalled)
                GM_registerMenuCommand(`${menu.state.symbols[0]} ${app.msgs.menuLabel_disabled}`,
                    () => modals.open('about'), tooltipsSupported ? { title: ' ' } : undefined )

            // ...or add settings entries
            else {
                const re_all = new RegExp(`^(${app.msgs.menuLabel_all}|all|any|every)$`, 'i')

                // Add setting entries
                Object.keys(settings.controls).forEach(key => {
                    const settingIsEnabled = config[key] ^ /disabled|hidden/i.test(key)
                    const menuLabel = `${ settings.controls[key].symbol || menu.state.symbols[+settingIsEnabled] } `
                                    + settings.controls[key].label
                                    + ( settings.controls[key].type == 'toggle' ? menu.state.separator
                                                                                + menu.state.words[+settingIsEnabled]
                                                                                : `— ${settings.controls[key].status}` )
                    menu.ids.push(GM_registerMenuCommand(menuLabel, () => {
                        if (settings.controls[key].type == 'toggle') {
                            settings.save(key, !config[key])
                            notify(`${settings.controls[key].label}: ${
                                menu.state.words[+(/disabled|hidden/i.test(key) ^ config[key])]}`)
                        } else if (key == 'replyLanguage') {
                            while (true) {
                                let replyLang = prompt(
                                    `${app.msgs.prompt_updateReplyLang}:`, config.replyLanguage)
                                if (replyLang == null) break // user cancelled so do nothing
                                else if (!/\d/.test(replyLang)) { // valid reply language set
                                    replyLang = ( // auto-case for menu/alert aesthetics
                                        replyLang.length < 4 || replyLang.includes('-') ? replyLang.toUpperCase()
                                            : replyLang.charAt(0).toUpperCase() + replyLang.slice(1).toLowerCase() )
                                    settings.save('replyLanguage', replyLang || env.browser.language)
                                    modals.alert(( app.msgs.alert_replyLangUpdated ) + '!', // title
                                        ( app.msgs.appName ) + ' ' // msg
                                            + ( app.msgs.alert_willReplyIn ) + ' '
                                            + ( replyLang || app.msgs.alert_yourSysLang) + '.'
                                    )
                                    break
                                }
                            }
                        } else if (key == 'replyTopic') {
                            let replyTopic = prompt(( app.msgs.prompt_updateReplyTopic )
                                + ' (' + ( app.msgs.prompt_orEnter ) + ' \'ALL\'):', config.replyTopic)
                            if (replyTopic != null) { // user didn't cancel
                                replyTopic = toTitleCase(replyTopic.toString()) // for menu/alert aesthetics
                                settings.save('replyTopic',
                                    !replyTopic || re_all.test(replyTopic) ? app.msgs.menuLabel_all : replyTopic)
                                modals.alert(`${app.msgs.alert_replyTopicUpdated}!`,
                                    `${app.msgs.appName} ${app.msgs.alert_willAnswer} `
                                        + ( !replyTopic || re_all.test(replyTopic) ? app.msgs.alert_onAllTopics
                                            : `${app.msgs.alert_onTopicOf} ${replyTopic}` )
                                        + '!'
                                )
                            }
                        } else if (key == 'replyInterval') {
                            while (true) {
                                const replyInterval = prompt(
                                    `${app.msgs.prompt_updateReplyInt}:`, config.replyInterval)
                                if (replyInterval == null) break // user cancelled so do nothing
                                else if (!isNaN(parseInt(replyInterval, 10)) && parseInt(replyInterval, 10) > 4) {
                                    settings.save('replyInterval', parseInt(replyInterval, 10))
                                    modals.alert(( app.msgs.alert_replyIntUpdated ) + '!', // title
                                        ( app.msgs.appName ) + ' ' // msg
                                            + ( app.msgs.alert_willReplyEvery ) + ' '
                                            + replyInterval + ' ' + ( app.msgs.unit_seconds ) + '.'
                                    )
                                    break
                                }
                            }
                        }
                        syncConfigToUI({ updatedKey: key })
                    }, tooltipsSupported ? { title: settings.controls[key].helptip || ' ' } : undefined))
                })
            }

            // Add About entry
            const aboutLabel = `💡 ${app.msgs.menuLabel_about} ${app.msgs.appName}`
            menu.ids.push(GM_registerMenuCommand(aboutLabel, () => modals.open('about'),
                tooltipsSupported ? { title: ' ' } : undefined ))

            // Add Donate entry
            if (!env.extensionInstalled) {
                const donateLabel = `💖 ${app.msgs.menuLabel_donate}`
                menu.ids.push(GM_registerMenuCommand(donateLabel, () => modals.open('donate'),
                    tooltipsSupported ? { title: ' ' } : undefined ))
            }
        },

        refresh() {
            if (typeof GM_unregisterMenuCommand == 'undefined') return
            for (const id of menu.ids) { GM_unregisterMenuCommand(id) } menu.register()
        }
    }

    function updateCheck() {
        xhr({
            method: 'GET', url: app.urls.update + '?t=' + Date.now(),
            headers: { 'Cache-Control': 'no-cache' },
            onload: resp => {

                // Compare versions, alert if update found
                app.latestVer = /@version +(.*)/.exec(resp.responseText)[1]
                for (let i = 0 ; i < 4 ; i++) { // loop thru subver's
                    const currentSubVer = parseInt(app.version.split('.')[i], 10) || 0,
                          latestSubVer = parseInt(app.latestVer.split('.')[i], 10) || 0
                    if (currentSubVer > latestSubVer) break // out of comparison since not outdated
                    else if (latestSubVer > currentSubVer) // if outdated
                        return modals.open('update', 'available')
                }

                // Alert to no update found, nav back to About
                modals.open('update', 'unavailable')
        }})
    }

    function toTitleCase(str) {
        if (!str) return ''
        const words = str.toLowerCase().split(' ')
        for (let i = 0 ; i < words.length ; i++) // for each word
            words[i] = words[i][0].toUpperCase() + words[i].slice(1) // title-case it
        return words.join(' ') // join'em back together
    }

    // Define FEEDBACK functions

    function notify(msg, pos = '', notifDuration = '', shadow = '') {

        // Strip state word to append colored one later
        const foundState = menu.state.words.find(word => msg.includes(word))
        if (foundState) msg = msg.replace(foundState, '')

        // Show notification
        chatgpt.notify(`${app.symbol} ${msg}`, pos, notifDuration, shadow || env.scheme == 'dark' ? '' : 'shadow')
        const notif = document.querySelector('.chatgpt-notif:last-child')

        // Append styled state word
        if (foundState) {
            const styledStateSpan = dom.create.elem('span')
            styledStateSpan.style.cssText = `color: ${
                foundState == menu.state.words[0] ? '#ef4848 ; text-shadow: rgba(255, 169, 225, 0.44) 2px 1px 5px'
                                                  : '#5cef48 ; text-shadow: rgba(255, 250, 169, 0.38) 2px 1px 5px' }`
            styledStateSpan.append(foundState) ; notif.append(styledStateSpan)
        }
    }

    // Define UI functions

    function syncConfigToUI(options) {
        if (options?.updatedKey == 'infinityMode') infinity[config.infinityMode ? 'activate' : 'deactivate']()
        else if (settings.controls[options?.updatedKey].type == 'prompt' && config.infinityMode)
            infinity.restart({ target: options?.updatedKey == 'replyInterval' ? 'self' : 'new' })
        if (/infinityMode|toggleHidden/.test(options?.updatedKey)) toggles.sidebar.update.state()
        menu.refresh() // prefixes/suffixes
    }

    function getScheme() {
        return document.documentElement.className
            || (window.matchMedia?.('(prefers-color-scheme: dark)')?.matches ? 'dark' : 'light')
    }

    chatgpt.isIdle = function() { // replace waiting for chat to start in case of interrupts
        return new Promise(resolve => { // when stop btn missing
            new MutationObserver((_, obs) => {
                if (!chatgpt.getStopBtn()) { obs.disconnect(); resolve() }
            }).observe(document.body, { childList: true, subtree: true })
        })
    }

    // Define INFINITY MODE functions

    const infinity = {

        async activate() {
            if (env.browser.isMobile && chatgpt.sidebar.isOn()) chatgpt.sidebar.hide()
            await new Promise(resolve => setTimeout(resolve, 500)) // sleep 500ms
            await new Promise(resolve => setTimeout(resolve, 3000)) // sleep 3s
            if (!document.querySelector('[data-message-author-role]') // new chat reset due to OpenAI bug
                && config.infinityMode) // ...and toggle still active
                    chatgpt.send(activatePrompt) // ...so prompt again
            await chatgpt.isIdle()
            if (config.infinityMode && !infinity.isActive) // double-check in case de-activated before scheduled
                infinity.isActive = setTimeout(infinity.continue, parseInt(config.replyInterval, 10) * 1000)
        },

        async continue() {
            if (!config.autoScrollDisabled) try { chatgpt.scrollToBottom() } catch(err) {}
            chatgpt.send('המשך בלי לשנות את התוכן')
            await chatgpt.isIdle() // before starting delay till next iteration
            if (infinity.isActive) // replace timer
                infinity.isActive = setTimeout(infinity.continue, parseInt(config.replyInterval, 10) * 1000)
        },

        deactivate() {
            if (chatgpt.getStopBtn()) chatgpt.stop()
            clearTimeout(infinity.isActive) ; infinity.isActive = null
        },

        async restart(options = { target: 'new' }) {
            if (options.target == 'new') {
                infinity.deactivate() ; setTimeout(() => infinity.activate(), 750)
            } else {
                clearTimeout(infinity.isActive) ; infinity.isActive = null ; await chatgpt.isIdle()
                if (config.infinityMode && !infinity.isActive) // double-check in case de-activated before scheduled
                    infinity.isActive = setTimeout(infinity.continue, parseInt(config.replyInterval, 10) * 1000)
            }
        }
    }

    // Run MAIN routine

    // Create browser TOOLBAR MENU or DISABLE SCRIPT if extension installed
    env.extensionInstalled = await Promise.race([
        new Promise(resolve => {
            (function checkExtensionInstalled() {
                if (document.documentElement.hasAttribute('chatgpt-infinity-extension-installed')) resolve(true)
                else setTimeout(checkExtensionInstalled, 200)
            })()
        }), new Promise(resolve => setTimeout(() => resolve(false), 1500))])

    menu.register() ; if (env.extensionInstalled) return

    // Init BROWSER/UI props
    await Promise.race([chatgpt.isLoaded(), new Promise(resolve => setTimeout(resolve, 5000))]) // initial UI loaded
    await chatgpt.sidebar.isLoaded()
    env.ui = { firstLink: chatgpt.getNewChatLink() }

    // Add LISTENER to auto-disable Infinity Mode
    if ('hidden' in document) // ...if Page Visibility API supported
        document.onvisibilitychange = () => {
            if (config.infinityMode) {
                settings.save('infinityMode', false) ; syncConfigToUI({ updatedKey: 'infinityMode' }) }
        }

    // Add STARS styles
    ['brs', 'wrs'].forEach(cssType => document.head.append(dom.create.style(GM_getResourceText(`${cssType}CSS`))))

    toggles.dependencies.import({ app, env, notify, syncConfigToUI })
    toggles.sidebar.insert()

    // Auto-start if enabled
    if (config.autoStart) {
        settings.save('infinityMode', true) ; syncConfigToUI({ updatedKey: 'infinityMode' })
        notify(`${app.msgs.menuLabel_autoStart}: ${app.msgs.state_on.toUpperCase()}`)
    }

    // Monitor NODE CHANGES to maintain sidebar toggle visibility
    new MutationObserver(() => {
        if (!config.toggleHidden && !document.getElementById(toggles.sidebar.ids.navicon)
            && toggles.sidebar.status != 'inserting') {
                toggles.sidebar.status = 'missing' ; toggles.sidebar.insert() }
    }).observe(document.body, { attributes: true, subtree: true })

    // Monitor SCHEME PREF changes to update sidebar toggle + modal colors
    new MutationObserver(handleSchemePrefChange).observe( // for site scheme pref changes
        document.documentElement, { attributes: true, attributeFilter: ['class'] })
    window.matchMedia('(prefers-color-scheme: dark)').addEventListener( // for browser/system scheme pref changes
        'change', () => requestAnimationFrame(handleSchemePrefChange))
    function handleSchemePrefChange() {
        const displayedScheme = getScheme()
        if (env.scheme != displayedScheme) {
            env.scheme = displayedScheme ; toggles.sidebar.update.color() ; modals.stylize() }
    }

    // Disable distracting SIDEBAR CLICK-ZOOM effect
    if (!document.documentElement.hasAttribute('sidebar-click-zoom-observed')) {
        new MutationObserver(mutations => mutations.forEach(({ target }) => {
            if (target.closest('[class*=sidebar]') // include sidebar divs
                && !target.id.endsWith('-knob-span') // exclude our toggles.sidebar
                && target.style.transform != 'none' // click-zoom occurred
            ) target.style.transform = 'none'
        })).observe(document.body, { attributes: true, subtree: true, attributeFilter: ['style'] })
        document.documentElement.setAttribute('sidebar-click-zoom-observed', true)
    }

})()