diff --git a/.env b/.env index 7bf3a19..170a182 100644 --- a/.env +++ b/.env @@ -18,6 +18,12 @@ EMULATOR_ENABLED=true # Set the hostname HOSTNAME=myrient.mahou.one +# OpenAI-compatible API settings +AI_ENABLED=true +AI_API_KEY=gsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +AI_API_URL=https://api.groq.com/openai/v1/chat/completions +AI_MODEL=openai/gpt-oss-120b + # Run docker-compose.dev.yml for running locally # Database Configuration POSTGRES_HOST=localhost diff --git a/README.md b/README.md index 3c076c8..55a26a8 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,13 @@ To ensure OpenGraph metadata embed for chat apps works correctly, please be sure # Metadata To enable metadata synchronize and matching, you will need to create a developer application in the [Twitch TV Developer Console](https://dev.twitch.tv/console) and then add your client id to `TWITCH_CLIENT_ID` in `.env` or `docker-compose.yml` along with adding your client secret to `TWITCH_CLIENT_SECRET`. Metadata takes about half an hour to synchronize from IGDB to your database, and about another half an hour to match via Postgres Full Text Search. Once all other database maintenance operations are done, the database will attempt to match anything that still isn't matched using a much slower fuzzy trigram search that can take up to a day to complete. These processes won't run again until a new crawl of myrient has been performed and the file count has increased. +# AI Chat Assistant +The search engine includes an optional AI chat assistant that can help users find games and answer questions. The AI assistant appears as a floating button in the bottom-right corner of all pages. You will have to fill API configuration in `.env` or `docker-compose.yml` to enable the AI chat assistant. + +The AI chat is OpenAI compatible, so you can use any compatible providers, like ChatGPT, Gemini, Ollama etc. We recommend using [Groq](https://groq.com) with `openai/gpt-oss-120b`, as it has excellent performance, great reasoning and generous limits for free usage. + + # Contributing -You know the usual fluff. -Is there a missing category or string association? `lib/categories.json` and any of the files under `lib/json/relatedkeywords` can both updated to include these. If you do update/improve these, please put in a pull request so that it can be added to the public hosted server, as well. +You know the usual fluff. +Is there a missing category or string association? `lib/categories.json` and any of the files under `lib/json/relatedkeywords` can both updated to include these. If you do update/improve these, please put in a pull request so that it can be added to the public hosted server, as well. Pull requests are always welcome. Make sure to make any changes clear in your pull request, and if possible, run any files you've modified through prettier. \ No newline at end of file diff --git a/config/locales/ar.json b/config/locales/ar.json index e6e1c5a..2bd2ef0 100644 --- a/config/locales/ar.json +++ b/config/locales/ar.json @@ -156,6 +156,25 @@ "back_home": "العودة إلى الصفحة الرئيسية", "go_back": "رجوع" }, + "ai_chat": { + "title": "مساعد الذكاء الاصطناعي", + "button_tooltip": "مساعد الذكاء الاصطناعي", + "welcome": { + "title": "مساعد الذكاء الاصطناعي", + "description": "يمكنني مساعدتك في العثور على ألعاب الريترو، وتقديم توصيات الألعاب، والإجابة على الأسئلة حول استخدام محرك البحث." + }, + "suggestions": { + "game_recommendations": "ما هي الألعاب التي توصي بها لجهاز Nintendo 64؟", + "search_tips": "كيف أبحث عن مناطق معينة؟", + "gaming_history": "أخبرني عن أجهزة الألعاب الريترو" + }, + "input_placeholder": "اسألني عن أي شيء...", + "typing_indicator": "الذكاء الاصطناعي يفكر", + "error": { + "network": "تعذر الاتصال بخدمة الذكاء الاصطناعي. يرجى التحقق من اتصال الإنترنت والمحاولة مرة أخرى.", + "generic": "آسف، أواجه مشاكل في الاتصال الآن. يرجى المحاولة مرة أخرى لاحقاً." + } + }, "languages": { "en": "English", "es": "Español", diff --git a/config/locales/bn.json b/config/locales/bn.json index ba9b3d4..fa57eb8 100644 --- a/config/locales/bn.json +++ b/config/locales/bn.json @@ -156,6 +156,25 @@ "back_home": "হোম পেজে ফিরে যান", "go_back": "পেছনে যান" }, + "ai_chat": { + "title": "এআই সহায়ক", + "button_tooltip": "এআই সহায়ক", + "welcome": { + "title": "এআই সহায়ক", + "description": "আমি আপনাকে রেট্রো গেম খুঁজতে, গেমের সুপারিশ দিতে এবং সার্চ ইঞ্জিন ব্যবহার সম্পর্কে প্রশ্নের উত্তর দিতে সাহায্য করতে পারি।" + }, + "suggestions": { + "game_recommendations": "Nintendo 64-এর জন্য আপনি কোন গেমগুলি সুপারিশ করেন?", + "search_tips": "আমি কীভাবে নির্দিষ্ট অঞ্চলের জন্য সার্চ করব?", + "gaming_history": "রেট্রো গেমিং কনসোল সম্পর্কে আমাকে বলুন" + }, + "input_placeholder": "আমাকে যেকোনো কিছু জিজ্ঞাসা করুন...", + "typing_indicator": "এআই চিন্তা করছে", + "error": { + "network": "এআই সেবার সাথে সংযোগ করতে পারছি না। অনুগ্রহ করে আপনার ইন্টারনেট সংযোগ পরীক্ষা করুন এবং আবার চেষ্টা করুন।", + "generic": "দুঃখিত, এখন আমার সংযোগে সমস্যা হচ্ছে। অনুগ্রহ করে পরে আবার চেষ্টা করুন।" + } + }, "languages": { "en": "English", "es": "Español", @@ -169,7 +188,7 @@ "tr": "Türkçe", "it": "Italiano", "romaji": "Romaji", - "hi": "हिन्दी", + "hi": "हिন्दी", "ar": "العربية", "bn": "বাংলা", "ru": "Русский" diff --git a/config/locales/de.json b/config/locales/de.json index ae5ebaf..4a6c38e 100644 --- a/config/locales/de.json +++ b/config/locales/de.json @@ -156,6 +156,25 @@ "back_home": "Zurück zur Startseite", "go_back": "Zurück" }, + "ai_chat": { + "title": "KI-Assistent", + "button_tooltip": "KI-Assistent", + "welcome": { + "title": "KI-Assistent", + "description": "Ich kann Ihnen helfen, Retro-Spiele zu finden, Spiel-Empfehlungen zu geben und Fragen zur Nutzung der Suchmaschine zu beantworten." + }, + "suggestions": { + "game_recommendations": "Welche Spiele empfehlen Sie für Nintendo 64?", + "search_tips": "Wie suche ich nach bestimmten Regionen?", + "gaming_history": "Erzählen Sie mir von Retro-Spielkonsolen" + }, + "input_placeholder": "Fragen Sie mich etwas...", + "typing_indicator": "KI denkt nach", + "error": { + "network": "Verbindung zum KI-Service nicht möglich. Überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut.", + "generic": "Entschuldigung, ich habe gerade Verbindungsprobleme. Bitte versuchen Sie es später erneut." + } + }, "languages": { "en": "English", "es": "Español", @@ -174,4 +193,4 @@ "bn": "বাংলা", "ru": "Русский" } -} +} \ No newline at end of file diff --git a/config/locales/en.json b/config/locales/en.json index a0f3b8e..1ba7588 100644 --- a/config/locales/en.json +++ b/config/locales/en.json @@ -156,6 +156,25 @@ "back_home": "Back to Home", "go_back": "Go Back" }, + "ai_chat": { + "title": "AI Assistant", + "button_tooltip": "AI Assistant", + "welcome": { + "title": "AI Assistant", + "description": "I can help you find retro games, provide gaming recommendations, and answer questions about using the search engine." + }, + "suggestions": { + "game_recommendations": "What games do you recommend for Nintendo 64?", + "search_tips": "How do I search for specific regions?", + "gaming_history": "Tell me about retro gaming consoles" + }, + "input_placeholder": "Ask me anything...", + "typing_indicator": "AI is thinking", + "error": { + "network": "Unable to connect to the AI service. Please check your internet connection and try again.", + "generic": "Sorry, I'm having trouble connecting right now. Please try again later." + } + }, "languages": { "en": "English", "es": "Español", @@ -174,4 +193,4 @@ "bn": "বাংলা", "ru": "Русский" } -} +} \ No newline at end of file diff --git a/config/locales/es.json b/config/locales/es.json index 7c69eef..56157a8 100644 --- a/config/locales/es.json +++ b/config/locales/es.json @@ -156,6 +156,25 @@ "back_home": "Volver al Inicio", "go_back": "Volver atrás" }, + "ai_chat": { + "title": "Asistente de IA", + "button_tooltip": "Asistente de IA", + "welcome": { + "title": "Asistente de IA", + "description": "Puedo ayudarte a encontrar juegos retro, proporcionar recomendaciones de juegos y responder preguntas sobre el uso del motor de búsqueda." + }, + "suggestions": { + "game_recommendations": "¿Qué juegos recomiendas para Nintendo 64?", + "search_tips": "¿Cómo busco regiones específicas?", + "gaming_history": "Cuéntame sobre consolas de videojuegos retro" + }, + "input_placeholder": "Pregúntame cualquier cosa...", + "typing_indicator": "La IA está pensando", + "error": { + "network": "No se puede conectar con el servicio de IA. Revisa tu conexión a internet e inténtalo de nuevo.", + "generic": "Lo siento, tengo problemas para conectarme ahora mismo. Inténtalo más tarde." + } + }, "languages": { "en": "English", "es": "Español", diff --git a/config/locales/fr.json b/config/locales/fr.json index e33de32..67429e2 100644 --- a/config/locales/fr.json +++ b/config/locales/fr.json @@ -156,6 +156,25 @@ "back_home": "Retour à l'accueil", "go_back": "Retour" }, + "ai_chat": { + "title": "Assistant IA", + "button_tooltip": "Assistant IA", + "welcome": { + "title": "Assistant IA", + "description": "Je peux vous aider à trouver des jeux rétro, fournir des recommandations de jeux et répondre aux questions sur l'utilisation du moteur de recherche." + }, + "suggestions": { + "game_recommendations": "Quels jeux recommandez-vous pour Nintendo 64 ?", + "search_tips": "Comment rechercher des régions spécifiques ?", + "gaming_history": "Parlez-moi des consoles de jeux rétro" + }, + "input_placeholder": "Demandez-moi n'importe quoi...", + "typing_indicator": "L'IA réfléchit", + "error": { + "network": "Impossible de se connecter au service IA. Vérifiez votre connexion internet et réessayez.", + "generic": "Désolé, j'ai du mal à me connecter en ce moment. Veuillez réessayer plus tard." + } + }, "languages": { "en": "English", "es": "Español", @@ -169,7 +188,7 @@ "tr": "Türkçe", "it": "Italiano", "romaji": "Romaji", - "hi": "हिन्दी", + "hi": "हiन्दी", "ar": "العربية", "bn": "বাংলা", "ru": "Русский" diff --git a/config/locales/hi.json b/config/locales/hi.json index d6b4b03..d9da728 100644 --- a/config/locales/hi.json +++ b/config/locales/hi.json @@ -156,6 +156,25 @@ "back_home": "होम पर वापस जाएं", "go_back": "वापस जाएं" }, + "ai_chat": { + "title": "एआई सहायक", + "button_tooltip": "एआई सहायक", + "welcome": { + "title": "एआई सहायक", + "description": "मैं आपको रेट्रो गेम्स खोजने, गेम सुझाव देने और सर्च इंजन के उपयोग के बारे में प्रश्नों के उत्तर देने में मदद कर सकता हूं।" + }, + "suggestions": { + "game_recommendations": "Nintendo 64 के लिए आप कौन से गेम्स सुझाते हैं?", + "search_tips": "मैं विशिष्ट क्षेत्रों की खोज कैसे करूं?", + "gaming_history": "रेट्रो गेमिंग कंसोल के बारे में बताइए" + }, + "input_placeholder": "मुझसे कुछ भी पूछें...", + "typing_indicator": "एआई सोच रहा है", + "error": { + "network": "एआई सेवा से कनेक्ट नहीं हो सकता। कृपया अपना इंटरनेट कनेक्शन जांचें और फिर कोशिश करें।", + "generic": "खुशी है, मुझे अभी कनेक्शन में समस्या हो रही है। कृपया बाद में कोशिश करें।" + } + }, "languages": { "en": "English", "es": "Español", diff --git a/config/locales/it.json b/config/locales/it.json index be1c958..0c91363 100644 --- a/config/locales/it.json +++ b/config/locales/it.json @@ -156,6 +156,25 @@ "back_home": "Torna alla Home", "go_back": "Indietro" }, + "ai_chat": { + "title": "Assistente AI", + "button_tooltip": "Assistente AI", + "welcome": { + "title": "Assistente AI", + "description": "Posso aiutarti a trovare giochi retrò, fornire raccomandazioni sui giochi e rispondere a domande sull'utilizzo del motore di ricerca." + }, + "suggestions": { + "game_recommendations": "Che giochi consigli per Nintendo 64?", + "search_tips": "Come cerco regioni specifiche?", + "gaming_history": "Dimmi delle console retro" + }, + "input_placeholder": "Chiedimi qualsiasi cosa...", + "typing_indicator": "L'AI sta pensando", + "error": { + "network": "Impossibile connettersi al servizio AI. Controlla la tua connessione internet e riprova.", + "generic": "Mi dispiace, sto avendo problemi di connessione ora. Riprova più tardi." + } + }, "languages": { "en": "English", "es": "Español", @@ -169,7 +188,7 @@ "tr": "Türkçe", "it": "Italiano", "romaji": "Romaji", - "hi": "हिन्दी", + "hi": "हिन्दŀ", "ar": "العربية", "bn": "বাংলা", "ru": "Русский" diff --git a/config/locales/ja.json b/config/locales/ja.json index efd701d..a72e61a 100644 --- a/config/locales/ja.json +++ b/config/locales/ja.json @@ -156,6 +156,25 @@ "back_home": "ホームに戻る", "go_back": "戻る" }, + "ai_chat": { + "title": "AIアシスタント", + "button_tooltip": "AIアシスタント", + "welcome": { + "title": "AIアシスタント", + "description": "レトロゲームの検索、ゲームの推薦、検索エンジンの使用方法に関する質問にお答えします。" + }, + "suggestions": { + "game_recommendations": "Nintendo 64におすすめのゲームはありますか?", + "search_tips": "特定の地域で検索するにはどうすればいいですか?", + "gaming_history": "レトロゲーム機について教えてください" + }, + "input_placeholder": "何でもお聞きください...", + "typing_indicator": "AIが考えています", + "error": { + "network": "AIサービスに接続できません。インターネット接続を確認して、もう一度お試しください。", + "generic": "申し訳ございませんが、現在接続に問題があります。後ほど再度お試しください。" + } + }, "languages": { "en": "English", "es": "Español", diff --git a/config/locales/ko.json b/config/locales/ko.json index b3fa53d..c92226f 100644 --- a/config/locales/ko.json +++ b/config/locales/ko.json @@ -156,6 +156,25 @@ "back_home": "홈으로 돌아가기", "go_back": "뒤로 가기" }, + "ai_chat": { + "title": "AI 어시스턴트", + "button_tooltip": "AI 어시스턴트", + "welcome": { + "title": "AI 어시스턴트", + "description": "레트로 게임 찾기, 게임 추천 제공, 검색 엔진 사용에 대한 질문 답변을 도와드릴 수 있습니다." + }, + "suggestions": { + "game_recommendations": "Nintendo 64에 어떤 게임을 추천하시나요?", + "search_tips": "특정 지역을 어떻게 검색하나요?", + "gaming_history": "레트로 게임 콘솔에 대해 알려주세요" + }, + "input_placeholder": "무엇이든 물어보세요...", + "typing_indicator": "AI가 생각 중입니다", + "error": { + "network": "AI 서비스에 연결할 수 없습니다. 인터넷 연결을 확인하고 다시 시도해 주세요.", + "generic": "죄송합니다. 지금 연결에 문제가 있습니다. 나중에 다시 시도해 주세요." + } + }, "languages": { "en": "English", "es": "Español", diff --git a/config/locales/pl.json b/config/locales/pl.json index 9ef8d2e..fa179c0 100644 --- a/config/locales/pl.json +++ b/config/locales/pl.json @@ -156,6 +156,25 @@ "back_home": "Powrót do strony głównej", "go_back": "Wróć" }, + "ai_chat": { + "title": "Asystent AI", + "button_tooltip": "Asystent AI", + "welcome": { + "title": "Asystent AI", + "description": "Mogę pomóc znaleźć retro gry, udzielić rekomendacji gier i odpowiedzieć na pytania dotyczące używania wyszukiwarki." + }, + "suggestions": { + "game_recommendations": "Jakie gry polecasz na Nintendo 64?", + "search_tips": "Jak szukać określonych regionów?", + "gaming_history": "Opowiedz mi o retro konsolach do gier" + }, + "input_placeholder": "Zapytaj mnie o cokolwiek...", + "typing_indicator": "AI myśli", + "error": { + "network": "Nie można połączyć się z usługą AI. Sprawdź połączenie internetowe i spróbuj ponownie.", + "generic": "Przepraszam, mam teraz problemy z połączeniem. Spróbuj ponownie później." + } + }, "languages": { "en": "English", "es": "Español", @@ -169,7 +188,7 @@ "tr": "Türkçe", "it": "Italiano", "romaji": "Romaji", - "hi": "हिन्दी", + "hi": "हिन्दŀ", "ar": "العربية", "bn": "বাংলা", "ru": "Русский" diff --git a/config/locales/pt.json b/config/locales/pt.json index c13d25e..2faf75e 100644 --- a/config/locales/pt.json +++ b/config/locales/pt.json @@ -68,7 +68,7 @@ "title": "Configurações", "search_columns": { "title": "Colunas de Busca", - "tooltip": "Seleciona em quais colunas o buscador vai pesquisar." + "tooltip": "Seleciona em quais colunas o mecanismo de busca vai pesquisar." }, "score_multiplier": { "title": "Multiplicador de Relevância", @@ -78,7 +78,7 @@ "title": "Opções avançadas", "fuzzy": { "label": "Busca aproximada", - "tooltip": "Valor entre 0,00 e 1,00 que determina o quão similar uma palavra precisa ser para ser considerada uma correspondência (distância Levenshtein). Valor mais alto permite correspondências menos exatas. Valor 0 desativa esta função." + "tooltip": "Valor entre 0,00 e 1,00 que determina o quão similar uma palavra precisa ser para ser considerada uma correspondência (distância Levenshtein). Valor mais alto permite correspondências menos exatas. Valor 0 desabilita esta função." }, "prefix": { "label": "Permitir Prefixos", @@ -86,7 +86,7 @@ }, "match_all": { "label": "Corresponder Todas as Palavras", - "tooltip": "Exige que todas as palavras da busca sejam encontradas nos resultados." + "tooltip": "Requer que todas as palavras da busca sejam encontradas nos resultados." }, "hide_non_game": { "label": "Ocultar Conteúdo Não-Jogo", @@ -123,7 +123,7 @@ "see_about": "Veja a página {{link}} para mais informações.", "no_data": "Não há dados de emulador disponíveis.", "https": "Conexão insegura: Alguns emuladores precisam de HTTPS para funcionar corretamente. Esta página não está configurada corretamente.", - "not_available_tooltip": "A emulação web não está disponível para este título pois não é um jogo ou a plataforma não é suportada." + "not_available_tooltip": "A emulação web não está disponível para este título porque não é um jogo ou a plataforma não é suportada." }, "console": { "about": "Este é um emulador online que executa jogos diretamente do arquivo público do Myrient.", @@ -156,6 +156,25 @@ "back_home": "Voltar para a Página Inicial", "go_back": "Voltar" }, + "ai_chat": { + "title": "Assistente IA", + "button_tooltip": "Assistente IA", + "welcome": { + "title": "Assistente IA", + "description": "Posso ajudar a encontrar jogos retrô, fornecer recomendações de jogos e responder perguntas sobre o uso da busca." + }, + "suggestions": { + "game_recommendations": "Que jogos recomenda para Nintendo 64?", + "search_tips": "Como pesquisar por regiões específicas?", + "gaming_history": "Conte-me sobre consoles de videogames antigos" + }, + "input_placeholder": "Pergunte-me qualquer coisa...", + "typing_indicator": "A IA está pensando", + "error": { + "network": "Não foi possível conectar ao serviço de IA. Tente novamente mais tarde.", + "generic": "Desculpe, estou com problemas de conexão agora. Tente novamente mais tarde." + } + }, "languages": { "en": "English", "es": "Español", diff --git a/config/locales/romaji.json b/config/locales/romaji.json index 1c412a1..646e1ee 100644 --- a/config/locales/romaji.json +++ b/config/locales/romaji.json @@ -156,6 +156,25 @@ "back_home": "Hōmu ni modoru", "go_back": "Modoru" }, + "ai_chat": { + "title": "AI Ashisutanto", + "button_tooltip": "AI Ashisutanto", + "welcome": { + "title": "AI Ashisutanto", + "description": "Retoro geemu no kensaku, geemu no suisen, kensaku enjin no shiyouhouhou ni kansuru shitsumon ni otae dekimasu." + }, + "suggestions": { + "game_recommendations": "Nintendo 64 ni osusume no geemu wa arimasu ka?", + "search_tips": "Tokutei no chiiki de kensaku suru ni wa dou sureba ii desu ka?", + "gaming_history": "Retoro geemu ki ni tsuite oshiete kudasai" + }, + "input_placeholder": "Nandemo okiki kudasai...", + "typing_indicator": "AI ga kangaete imasu", + "error": { + "network": "AI saabisu ni setsuzoku dekimasen. Intaanetto setsuzoku wo kakunin shite, mou ichido otameshi kudasai.", + "generic": "Moushiwake gozaimasen ga, genzai setsuzoku ni mondai ga arimasu. Nochihodo saido otameshi kudasai." + } + }, "languages": { "en": "English", "es": "Español", diff --git a/config/locales/ru.json b/config/locales/ru.json index 5b9019c..7040264 100644 --- a/config/locales/ru.json +++ b/config/locales/ru.json @@ -155,6 +155,25 @@ "back_home": "Вернуться на главную", "go_back": "Назад" }, + "ai_chat": { + "title": "ИИ Помощник", + "button_tooltip": "ИИ Помощник", + "welcome": { + "title": "ИИ Помощник", + "description": "Я могу помочь найти ретро-игры, предоставить игровые рекомендации и ответить на вопросы об использовании поисковой системы." + }, + "suggestions": { + "game_recommendations": "Какие игры вы рекомендуете для Nintendo 64?", + "search_tips": "Как искать определённые регионы?", + "gaming_history": "Расскажите о ретро игровых консолях" + }, + "input_placeholder": "Спросите меня о чём угодно...", + "typing_indicator": "ИИ думает", + "error": { + "network": "Не удаётся подключиться к службе ИИ. Проверьте подключение к интернету и попробуйте снова.", + "generic": "Извините, у меня проблемы с подключением прямо сейчас. Попробуйте позже." + } + }, "languages": { "en": "English", "es": "Español", diff --git a/config/locales/tr.json b/config/locales/tr.json index eb65f27..b409e84 100644 --- a/config/locales/tr.json +++ b/config/locales/tr.json @@ -156,6 +156,25 @@ "back_home": "Ana Sayfaya Dön", "go_back": "Geri Dön" }, + "ai_chat": { + "title": "AI Asistanı", + "button_tooltip": "AI Asistanı", + "welcome": { + "title": "AI Asistanı", + "description": "Retro oyunlar bulmanıza, oyun önerileri sunmama ve arama motoru kullanımıyla ilgili sorularınızı yanıtlamama yardımcı olabilirim." + }, + "suggestions": { + "game_recommendations": "Nintendo 64 için hangi oyunları önerirsiniz?", + "search_tips": "Belirli bölgeleri nasıl ararım?", + "gaming_history": "Retro oyun konsolları hakkında bilgi verin" + }, + "input_placeholder": "Bana her şeyi sorabilirsiniz...", + "typing_indicator": "AI düşünüyor", + "error": { + "network": "AI hizmetine bağlanılamıyor. İnternet bağlantınızı kontrol edin ve tekrar deneyin.", + "generic": "Üzgünüm, şu anda bağlantı sorunum var. Lütfen daha sonra tekrar deneyin." + } + }, "languages": { "en": "English", "es": "Español", diff --git a/config/locales/zh.json b/config/locales/zh.json index a7eac2b..b595c14 100644 --- a/config/locales/zh.json +++ b/config/locales/zh.json @@ -156,6 +156,25 @@ "back_home": "返回首页", "go_back": "返回" }, + "ai_chat": { + "title": "AI助手", + "button_tooltip": "AI助手", + "welcome": { + "title": "AI助手", + "description": "我可以帮助您找到复古游戏,提供游戏推荐,并回答有关使用搜索引擎的问题。" + }, + "suggestions": { + "game_recommendations": "您推荐Nintendo 64有什么游戏?", + "search_tips": "如何搜索特定地区?", + "gaming_history": "告诉我关于复古游戏机的信息" + }, + "input_placeholder": "问我任何问题...", + "typing_indicator": "AI正在思考", + "error": { + "network": "无法连接到AI服务。请检查您的互联网连接并重试。", + "generic": "抱歉,我现在连接有问题。请稍后再试。" + } + }, "languages": { "en": "English", "es": "Español", diff --git a/server.js b/server.js index eef03bd..8237ff3 100644 --- a/server.js +++ b/server.js @@ -532,6 +532,110 @@ app.get("/api/emulators", function (req, res) { res.json(emulatorsData); }); +app.post("/api/ai-chat", async function (req, res) { + try { + const { message } = req.body; + + if (!message || typeof message !== 'string') { + return res.status(400).json({ error: 'Message is required' }); + } + + // Check if AI is enabled and configured + const aiEnabled = process.env.AI_ENABLED === 'true'; + const apiKey = process.env.AI_API_KEY; + const apiUrl = process.env.AI_API_URL || 'https://api.openai.com/v1/chat/completions'; + const model = process.env.AI_MODEL || 'gpt-3.5-turbo'; + + if (!aiEnabled) { + return res.status(503).json({ + error: 'AI chat is currently disabled. Please contact the administrator.' + }); + } + + if (!apiKey) { + return res.status(503).json({ + error: 'AI service is not configured. Please contact the administrator.' + }); + } + + // Create system prompt with context about Myrient + const systemPrompt = `You are a helpful AI assistant for the Myrient Search Engine, a website that helps users find and search through retro games and ROMs. + +About Myrient: +- Myrient is a preservation project that offers a comprehensive collection of retro games +- Users can search for games by filename, category, type, and region +- The site includes an emulator feature for playing games directly in the browser +- The search engine indexes thousands of games from various gaming systems and regions + +Your role: +- Help users find games they're looking for +- Provide information about gaming history, consoles, and game recommendations +- Answer questions about how to use the search features +- Be knowledgeable about retro gaming but stay focused on being helpful +- Keep responses concise and friendly +- If users ask about downloading or legal issues, remind them that Myrient focuses on preservation + +Current search context: The user is on a retro gaming search website and may be looking for specific games or gaming information.`; + + const aiResponse = await fetch(apiUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${apiKey}`, + 'User-Agent': 'Myrient-Search-Engine/1.0' + }, + body: JSON.stringify({ + model: model, + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: message } + ], + max_tokens: 500, + temperature: 0.7, + stream: false + }) + }); + + if (!aiResponse.ok) { + const errorData = await aiResponse.json().catch(() => ({})); + console.error('AI API Error:', aiResponse.status, errorData); + + // Handle specific error cases + if (aiResponse.status === 401) { + return res.status(503).json({ + error: 'AI service authentication failed. Please contact the administrator.' + }); + } else if (aiResponse.status === 429) { + return res.status(429).json({ + error: 'AI service is currently busy. Please try again in a moment.' + }); + } else { + return res.status(503).json({ + error: 'AI service is temporarily unavailable. Please try again later.' + }); + } + } + + const aiData = await aiResponse.json(); + + if (!aiData.choices || aiData.choices.length === 0) { + return res.status(503).json({ + error: 'AI service returned an unexpected response.' + }); + } + + const response = aiData.choices[0].message.content.trim(); + + res.json({ response }); + + } catch (error) { + console.error('AI Chat Error:', error); + res.status(500).json({ + error: 'An unexpected error occurred. Please try again later.' + }); + } +}); + app.get("/proxy-image", async function (req, res, next) { const imageUrl = req.query.url; diff --git a/views/pages/index.ejs b/views/pages/index.ejs index a42c5fc..6d980a4 100644 --- a/views/pages/index.ejs +++ b/views/pages/index.ejs @@ -1,4 +1,4 @@ -<% +<% let ogPages = { "results": "opengraphresults", "info": "opengraphinfo" @@ -21,8 +21,57 @@ <%- include('../partials/footer'); %> + + + +