├── .dockerignore ├── .env.example ├── .gitignore ├── Dockerfile ├── README.md ├── chatgpt ├── access_token.js ├── chatgpt.js ├── moderations.js └── tokenCount.js ├── config └── config.js ├── configFile └── config.example.json ├── dashboard ├── dasboard.js ├── middleware │ └── auth.js ├── public │ ├── css │ │ ├── bulma.min.css │ │ ├── dashboard.css │ │ ├── index.css │ │ └── style.css │ ├── dashboard.html │ ├── images │ │ ├── github.png │ │ └── logo.png │ ├── index.html │ └── js │ │ ├── auth.js │ │ ├── dashboard.js │ │ ├── index.js │ │ ├── jquery-3.6.0.js │ │ └── style.js └── routes │ └── api.js ├── discord ├── discord_commands.js └── discord_helpers.js ├── huggingface ├── huggingface_ws.js ├── instruct-pix2pix │ └── instruct-pix2pix.js └── stablediffusion │ └── stableDiffusion.js ├── index.js ├── license.md ├── package-lock.json ├── package.json ├── proxyService ├── freeProxyList.js └── proxyService.js └── screen_shot ├── Screenshot_1.jpg ├── Screenshot_2.jpg ├── Screenshot_3.jpg ├── Screenshot_4.jpg ├── Screenshot_5.jpg └── Screenshot_6.jpg /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/* -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | DISCORD_BOT_TOKEN=..... 2 | DISCORD_CLIENT_ID=..... 3 | OPENAI_API_KEY=.... 4 | DASHBOARD_USERNAME=admin 5 | DASHBOARD_PASSWORD=admin -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | .env 3 | config.json -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine 2 | LABEL MAINTAINER Onur YILDIZ 3 | 4 | RUN mkdir discordChatGpt 5 | 6 | WORKDIR /discordChatGpt 7 | 8 | COPY package.json /discordChatGpt/ 9 | 10 | RUN npm install 11 | 12 | COPY . /discordChatGpt/ 13 | 14 | CMD ["npm","start"] -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Discord ChatGpt Bot 3 | 4 | The bot now uses the official ChatGpt API. :tada: This means you can expect more reliable and consistent responses from the bot. 5 | However, if you prefer to use the unofficial API version, you can always find it on the "non_official_api" branch. 6 | Thank you for using our bot and contributing to the project! 7 | 8 | We now have a convenient dashboard for configuring the bot, eliminating the need to restart it to modify settings. The bot runs on port 8080. Additionally, there are plans to integrate usage statistics into the dashboard. 9 | 10 | commands : 11 | 12 | * You can ask anything with ```/ask 'question'``` 13 | * You can generate images with ```/image 'prompt'``` 14 | * You can edit other members' pp with ```/remix @mentionuser prompt``` 15 | 16 | ## [You can test it on discord](https://discord.gg/xggt6w6Sz4) 17 | 18 | Screenshots : 19 | 20 | ![Screenshot_6](https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/master/screen_shot/Screenshot_6.jpg) 21 | 22 | ![Screenshot_1](https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/master/screen_shot/Screenshot_1.jpg) 23 | 24 | 25 | 26 | ![Screenshot_3](https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/master/screen_shot/Screenshot_3.jpg) 27 | 28 | 29 | 30 | ![Screenshot_4](https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/master/screen_shot/Screenshot_4.jpg) 31 | 32 | 33 | ![Screenshot_5](https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/master/screen_shot/Screenshot_5.jpg) 34 | 35 | ## How to run it? 36 | 37 | Firstly, you should rename ".env.example" file to ".env". 38 | After that you should fill it correctly. 39 | When you fill it, you can start it with two ways. 40 | 41 | ### with nodejs 42 | 43 | ``` 44 | 45 | npm install 46 | 47 | npm start 48 | 49 | ``` 50 | 51 | ### with docker 52 | 53 | ``` 54 | 55 | docker build -t discordchatgpt . 56 | 57 | docker run -p 8080:8080 -v discordchatgptconfig:/discordChatGpt/configFile discordchatgpt 58 | 59 | ``` 60 | -------------------------------------------------------------------------------- /chatgpt/access_token.js: -------------------------------------------------------------------------------- 1 | import OpenAITokenGen from "aikey"; 2 | 3 | export async function getAccessToken(){ 4 | const generator = new OpenAITokenGen(); 5 | let res = await generator.login(process.env.OPENAI_EMAIL, process.env.OPENAI_PASSWORD) 6 | 7 | return res.accessToken 8 | } 9 | -------------------------------------------------------------------------------- /chatgpt/chatgpt.js: -------------------------------------------------------------------------------- 1 | import config from '../config/config.js' 2 | import Moderations from './moderations.js' 3 | import tokenCount from './tokenCount.js' 4 | 5 | const chatGPT = { 6 | sendMessage: null, 7 | } 8 | 9 | chatGPT.sendMessage = async function (prompt) { 10 | 11 | const tokens = tokenCount(prompt) 12 | const MAX_TOKENS = config.get("MAX_TOKEN") 13 | 14 | if (tokens > MAX_TOKENS / 2) { 15 | return `Please limit your prompt to a maximum of ${parseInt(MAX_TOKENS / 2)} tokens. Thank you.` 16 | } 17 | 18 | const messages = [ 19 | { 20 | role: "system", 21 | content: config.get("CONVERSATION_START_PROMPT") != "" ? 22 | config.get("CONVERSATION_START_PROMPT") : 23 | "You are helpful assistant" 24 | }, 25 | { 26 | role: "user", 27 | content: prompt 28 | } 29 | ] 30 | 31 | const data = { 32 | model: config.get("OPENAI_MODEL"), 33 | messages, 34 | max_tokens: MAX_TOKENS - tokens 35 | } 36 | 37 | let res = await fetch("https://api.openai.com/v1/chat/completions", 38 | { 39 | method: "POST", 40 | headers: { 41 | "Content-Type": "application/json", 42 | "Authorization": `Bearer ${process.env.OPENAI_API_KEY}` 43 | }, 44 | body: JSON.stringify(data) 45 | }) 46 | res = await res.json() 47 | if(res.error){ 48 | console.error(res) 49 | } 50 | 51 | return { 52 | text: res.choices[0].message.content.trim(), 53 | usage: res.usage, 54 | tokens 55 | } 56 | } 57 | 58 | export async function askQuestion(question, cb, opts = {}) { 59 | try { 60 | let redFlag = await Moderations(question) 61 | if (redFlag) { 62 | cb("Your prompt contains harmful content!") 63 | return; 64 | } 65 | } catch (e) { 66 | console.log(e) 67 | cb(e) 68 | return; 69 | } 70 | 71 | try { 72 | const response = await chatGPT.sendMessage(question) 73 | 74 | if (!response.text) { 75 | throw "no response!" 76 | } 77 | cb(response.text) 78 | } catch (e) { 79 | cb("Oppss, something went wrong! (Error)") 80 | console.error("chat error : " + e) 81 | } 82 | } -------------------------------------------------------------------------------- /chatgpt/moderations.js: -------------------------------------------------------------------------------- 1 | export default async function Moderations(input) { 2 | let res = await fetch("https://api.openai.com/v1/moderations", 3 | { 4 | method: "POST", 5 | headers: { 6 | "Content-Type": "application/json", 7 | "Authorization": `Bearer ${process.env.OPENAI_API_KEY}` 8 | }, 9 | body: JSON.stringify({input}) 10 | }) 11 | res = await res.json() 12 | return res.results[0].flagged 13 | } -------------------------------------------------------------------------------- /chatgpt/tokenCount.js: -------------------------------------------------------------------------------- 1 | import { encode } from "gpt-3-encoder" 2 | 3 | export default function tokenCount(text){ 4 | return encode(text).length 5 | } -------------------------------------------------------------------------------- /config/config.js: -------------------------------------------------------------------------------- 1 | import fs from "fs/promises" 2 | const PATH = "./configFile/config.json" 3 | let config = { 4 | "OPENAI_MODEL":"gpt-3.5-turbo", 5 | "MAX_TOKEN":1000, 6 | "ENABLE_DIRECT_MESSAGES":false, 7 | "CONVERSATION_START_PROMPT":"", 8 | "USE_EMBED":true 9 | } 10 | 11 | load() 12 | 13 | function get(key){ 14 | return config[key] 15 | } 16 | 17 | function set(key,value){ 18 | if(config[key] == undefined){ 19 | console.log("Invalid config key : ",key) 20 | return; 21 | } 22 | config[key] = value 23 | } 24 | 25 | function save(){ 26 | fs.writeFile(PATH,JSON.stringify(config)).then(()=>{ 27 | console.log("Config saved!") 28 | }).catch((err)=>{ 29 | console.error("Config save error! : ",err) 30 | }) 31 | } 32 | 33 | function load(){ 34 | fs.readFile(PATH).then((data)=>{ 35 | try{ 36 | data = data.toString() 37 | config = JSON.parse(data) 38 | console.log(new Date()+" --- Config loaded") 39 | }catch(e){ 40 | console.error("Config file corrupted! : ",e) 41 | } 42 | }).catch(()=>{ 43 | save() 44 | }) 45 | } 46 | 47 | function getFullConfig(){ 48 | return {...config} 49 | } 50 | 51 | export default { 52 | save, 53 | load, 54 | set, 55 | get, 56 | getFullConfig 57 | } -------------------------------------------------------------------------------- /configFile/config.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "OPENAI_MODEL":"gpt-3.5-turbo", 3 | "MAX_TOKEN":1000, 4 | "ENABLE_DIRECT_MESSAGES":false, 5 | "CONVERSATION_START_PROMPT":"", 6 | "USE_EMBED":true 7 | } -------------------------------------------------------------------------------- /dashboard/dasboard.js: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import cookieParser from "cookie-parser"; 3 | import bodyParser from "body-parser"; 4 | 5 | import API_ROUTER from "./routes/api.js"; 6 | 7 | const app = express() 8 | 9 | app.use(express.static("./dashboard/public")) 10 | app.use(cookieParser()) 11 | app.use(bodyParser.urlencoded({ extended: false })) 12 | app.use(bodyParser.json()) 13 | 14 | let init = false 15 | export const JWT_SECRET = generateSecret() 16 | function generateSecret(){ 17 | let chars = "qwertyuopasdfghjklizxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789" 18 | let secret = "" 19 | for(let i=0;i<32;i++){ 20 | secret += chars[Math.floor(Math.random()*chars.length)] 21 | } 22 | return secret 23 | } 24 | 25 | app.use("/api",API_ROUTER) 26 | 27 | app.get("/logout",(req,res)=>{ 28 | res.cookie("auth","") 29 | res.redirect("/") 30 | }) 31 | 32 | export function initDashboard(){ 33 | if(init){ 34 | return; 35 | } 36 | 37 | app.listen(8080,()=>{ 38 | console.log(new Date() + " Dashboard listening on port 8080") 39 | }) 40 | } -------------------------------------------------------------------------------- /dashboard/middleware/auth.js: -------------------------------------------------------------------------------- 1 | import jwt from "jsonwebtoken"; 2 | import { JWT_SECRET } from "../dasboard.js"; 3 | 4 | export default function auth(req,res,next){ 5 | let cookie = req.cookies.auth 6 | if (!cookie) { 7 | return res.sendStatus(403) 8 | } 9 | 10 | try { 11 | jwt.verify(cookie, JWT_SECRET); 12 | next() 13 | } catch (e) { 14 | res.sendStatus(403) 15 | } 16 | } -------------------------------------------------------------------------------- /dashboard/public/css/dashboard.css: -------------------------------------------------------------------------------- 1 | body{ 2 | margin: 0; 3 | padding: 0; 4 | background: black; 5 | color: white; 6 | } 7 | 8 | #navbar{ 9 | display: flex; 10 | justify-content: space-around; 11 | align-items: center; 12 | padding: 10px; 13 | background-color: rgba(0, 0, 0, 0.1); 14 | position: sticky; 15 | top: 0; 16 | backdrop-filter: blur(3px); 17 | } 18 | 19 | #navbar img{ 20 | height: 80px; 21 | cursor: pointer; 22 | } 23 | 24 | #configlist{ 25 | max-width: 1000px; 26 | margin: auto; 27 | } 28 | 29 | .config{ 30 | display: flex; 31 | flex-direction: column; 32 | gap: 10px; 33 | margin-bottom: 15px; 34 | padding-bottom: 10px; 35 | border-bottom: 1px solid white; 36 | } 37 | 38 | .config label{ 39 | font-size: 26px; 40 | font-weight: bold; 41 | } 42 | 43 | .config span{ 44 | font-size: 20px; 45 | color: #dddddd; 46 | } 47 | 48 | .config input[type=checkbox]{ 49 | width: 30px; 50 | height: 30px; 51 | margin: auto; 52 | } 53 | a{ 54 | text-decoration: none; 55 | } 56 | button{ 57 | font-size: 20px; 58 | cursor: pointer; 59 | padding: 5px 20px; 60 | } 61 | 62 | #save_button{ 63 | display: block; 64 | margin: auto; 65 | } 66 | 67 | #oauth_discord{ 68 | display: block; 69 | color: white; 70 | font-size: 20px; 71 | margin: 20px 0; 72 | } -------------------------------------------------------------------------------- /dashboard/public/css/index.css: -------------------------------------------------------------------------------- 1 | body{ 2 | margin: 0; 3 | padding: 0; 4 | display: block; 5 | background-color: black; 6 | color: white; 7 | display: flex; 8 | justify-content: center; 9 | align-items: center; 10 | height: 100vh; 11 | } 12 | 13 | #loginform{ 14 | border: 1px solid white; 15 | display: flex; 16 | justify-content: center; 17 | align-items: center; 18 | flex-direction: column; 19 | width: 450px; 20 | height: 450px; 21 | gap: 30px; 22 | font-size: 24px; 23 | } 24 | 25 | #loginform input{ 26 | font-size: 24px; 27 | width: 60%; 28 | } 29 | 30 | #loginform label{ 31 | display: inline-block; 32 | font-size: 24px; 33 | width: 30%; 34 | } 35 | 36 | .field{ 37 | text-align: center; 38 | } 39 | 40 | #loginform img{ 41 | height: 100px; 42 | } 43 | 44 | #loginform button{ 45 | font-size: 20px; 46 | padding: 3px 20px; 47 | } -------------------------------------------------------------------------------- /dashboard/public/css/style.css: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap"); 2 | 3 | * { 4 | font-family: "Poppins", sans-serif; 5 | } 6 | 7 | html { 8 | scroll-behavior: smooth; 9 | background: #151515!important; 10 | } 11 | 12 | .blurple { 13 | color: #7289da; 14 | } 15 | .title .title.lined .subtitle { 16 | color: white!important; 17 | } 18 | #backtotop { 19 | display: inline-block; 20 | background-color: #7289d9; 21 | width: 50px; 22 | height: 50px; 23 | text-align: center; 24 | border-radius: 30px; 25 | position: fixed; 26 | bottom: 30px; 27 | right: 30px; 28 | transition: background-color 0.3s, opacity 0.5s, visibility 0.5s; 29 | opacity: 0; 30 | visibility: hidden; 31 | z-index: 1000; 32 | } 33 | 34 | #backtotop:hover { 35 | cursor: pointer; 36 | background-color: #333; 37 | } 38 | 39 | #backtotop:active { 40 | background-color: #555; 41 | } 42 | 43 | #backtotop.show { 44 | opacity: 0.4; 45 | visibility: visible; 46 | } 47 | 48 | .navbar-item, 49 | .navbar-link { 50 | -moz-transition: all 0.2s ease-in; 51 | -o-transition: all 0.2s ease-in; 52 | -webkit-transition: all 0.2s ease-in; 53 | transition: all 0.2s ease-in; 54 | } 55 | 56 | .navbar-item:hover { 57 | background-color: transparent !important; 58 | color: #7289da !important; 59 | } 60 | 61 | .navbar-link:hover { 62 | background-color: transparent !important; 63 | color: #7289da !important; 64 | } 65 | 66 | .navbar-menu { 67 | animation: navAnimOpen 0.2s ease-in-out; 68 | } 69 | 70 | @keyframes navAnimOpen { 71 | 0% { 72 | display: none; 73 | opacity: 0; 74 | max-height: 0; 75 | } 76 | 1% { 77 | display: block; 78 | opacity: 0; 79 | } 80 | 100% { 81 | opacity: 1; 82 | max-height: 396px; 83 | } 84 | from { 85 | opacity: 0; 86 | transform: translateY(-5px); 87 | } 88 | to { 89 | opacity: 1; 90 | transform: translateY(0px); 91 | } 92 | } 93 | 94 | nav, 95 | .navbar-menu { 96 | background-color: #000000 !important; 97 | } 98 | 99 | .navbar-item.nav-dark, 100 | .navbar-link.nav-dark { 101 | color: #fefefe !important; 102 | } 103 | 104 | .navbar-item, 105 | .navbar-link { 106 | color: white !important; 107 | } 108 | 109 | nav.nav-w { 110 | background: #080808 !important; 111 | box-shadow: 1px 2px 10px rgba(0, 0, 0, 0.1) !important; 112 | } 113 | 114 | .nav-w { 115 | background: #080808 !important; 116 | box-shadow: 100px 2px 10px rgba(0, 0, 0, 0.1) !important; 117 | } 118 | 119 | .mb-12 { 120 | margin-bottom: 6rem; 121 | } 122 | 123 | .mt-12 { 124 | margin-top: 6rem; 125 | } 126 | 127 | .ml-12 { 128 | margin-left: 6rem; 129 | } 130 | 131 | .mr-12 { 132 | margin-right: 6rem; 133 | } 134 | 135 | .img-col-ml-13 { 136 | margin-left: 13rem; 137 | } 138 | 139 | .img-col-mr-13 { 140 | margin-right: 13rem; 141 | } 142 | 143 | .has-image-centered { 144 | margin-left: auto; 145 | margin-right: auto; 146 | } 147 | .line.blurple { 148 | background: #7289d9; 149 | } 150 | 151 | .title.lined { 152 | margin-bottom: 0px; 153 | color: white!important; 154 | font-family: 'Uni Sans Demo', sans-serif!important; 155 | } 156 | 157 | .title { 158 | color: white!important; 159 | font-family: 'Uni Sans Demo', sans-serif!important; 160 | font-size: 50px; 161 | margin-bottom: 0rem !important; 162 | } 163 | 164 | .subtitle { 165 | color: white!important; 166 | } 167 | 168 | .button.is-blurple { 169 | background-color: #7289d9; 170 | border-color: transparent; 171 | color: #fff; 172 | } 173 | 174 | .navbar.is-fixed-top{ 175 | padding-left: 30px; 176 | padding-right: 30px; 177 | } 178 | 179 | .footer { 180 | background: #080808; 181 | padding: 2rem 1.5rem 2rem !important; 182 | } 183 | 184 | .checkbox { 185 | display: inline-flex; 186 | } 187 | .checkbox input{ 188 | zoom: 1.5; 189 | margin-bottom: 0.5rem; 190 | margin-left: 5px; 191 | } 192 | 193 | .login { 194 | position: fixed; 195 | } 196 | 197 | .logo { 198 | width: 100px; 199 | margin-bottom:20px 200 | } -------------------------------------------------------------------------------- /dashboard/public/dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ChatGPT Bot Dashboard 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 64 | 65 | 66 | 67 |
68 |
69 |

ChatGPT Discord Bot

70 |
71 |
72 | 80 |
81 | 82 | 83 | 84 |
85 |
86 |

OpenAI Model

87 |

88 | Choose which OPENAI model does the bot use? 89 |

90 |
91 |
92 | 98 |
99 |
100 |
101 |
102 |
103 |
104 |

Max Token

105 |

106 | The maximum number of tokens allowed for a prompt? 107 |

108 |
109 | 110 |
111 |
112 |
113 |
114 |
115 |

Conversation Start Prompt

116 |

117 | A little prompt to customize bot's responses behaviour 118 |

119 |
120 | 122 |
123 |
124 |
125 |
126 |
127 |

Enable Direct Messages

128 | 134 |
135 |
136 |
137 |
138 |

Use Embeds

139 | 145 |
146 |
147 |

148 | 149 | 151 |
152 | 153 | 154 | 155 | 174 | 175 | 176 | 177 | 178 | 179 | 184 | 189 | 190 | 191 | 192 | 193 | 194 | -------------------------------------------------------------------------------- /dashboard/public/images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/c3c58decfbf3ed107884a4b1cb2027535a0b8dd4/dashboard/public/images/github.png -------------------------------------------------------------------------------- /dashboard/public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/c3c58decfbf3ed107884a4b1cb2027535a0b8dd4/dashboard/public/images/logo.png -------------------------------------------------------------------------------- /dashboard/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ChatGPT Bot Login 9 | 10 | 11 | 12 | 13 | 14 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 |
29 | 50 |
51 |
52 |
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /dashboard/public/js/auth.js: -------------------------------------------------------------------------------- 1 | function checkAuth() { 2 | return new Promise(async (resolve) => { 3 | let res = await fetch("/api/checkauth", { 4 | credentials: "include" 5 | }) 6 | if (res.status == 200) { 7 | resolve(true) 8 | } else { 9 | resolve(false) 10 | } 11 | }) 12 | } 13 | 14 | checkAuth().then(res => { 15 | if (res && window.location.pathname == "/") { 16 | window.location = "/dashboard.html" 17 | } else if (!res && window.location.pathname != "/") { 18 | window.location = "/" 19 | } 20 | }) -------------------------------------------------------------------------------- /dashboard/public/js/dashboard.js: -------------------------------------------------------------------------------- 1 | const fields = { 2 | OPENAI_MODEL: document.getElementById("OPENAI_MODEL"), 3 | MAX_TOKEN: document.getElementById("MAX_TOKEN"), 4 | ENABLE_DIRECT_MESSAGES: document.getElementById("ENABLE_DIRECT_MESSAGES"), 5 | CONVERSATION_START_PROMPT: document.getElementById("CONVERSATION_START_PROMPT"), 6 | USE_EMBED: document.getElementById("USE_EMBED"), 7 | } 8 | const Success = document.getElementById("notiSuccess"); 9 | const Failure = document.getElementById("notiFail"); 10 | 11 | 12 | 13 | document.getElementById("save_button").addEventListener("click",saveConfig) 14 | 15 | async function getOAuthUrl(){ 16 | let res = await fetch("/api/oauthurl", { 17 | credentials: "include" 18 | }) 19 | 20 | if (res.status != 200) { 21 | return 22 | } 23 | 24 | res = await res.json() 25 | console.log(res) 26 | const a = document.getElementById("oauth_discord") 27 | a.href = res.url 28 | } 29 | getOAuthUrl() 30 | 31 | async function loadConfig() { 32 | let res = await fetch("/api/config", { 33 | credentials: "include" 34 | }) 35 | 36 | if (res.status != 200) { 37 | return window.location = "/" 38 | } 39 | 40 | res = await res.json() 41 | 42 | fields.OPENAI_MODEL.value = res.OPENAI_MODEL 43 | fields.MAX_TOKEN.value = res.MAX_TOKEN 44 | fields.ENABLE_DIRECT_MESSAGES.checked = res.ENABLE_DIRECT_MESSAGES 45 | fields.CONVERSATION_START_PROMPT.value = res.CONVERSATION_START_PROMPT 46 | fields.USE_EMBED.checked = res.USE_EMBED 47 | } 48 | 49 | async function saveConfig() { 50 | const data = { 51 | OPENAI_MODEL:fields.OPENAI_MODEL.value, 52 | MAX_TOKEN: fields.MAX_TOKEN.value, 53 | ENABLE_DIRECT_MESSAGES: fields.ENABLE_DIRECT_MESSAGES.checked, 54 | CONVERSATION_START_PROMPT: fields.CONVERSATION_START_PROMPT.value, 55 | USE_EMBED: fields.USE_EMBED.checked, 56 | } 57 | 58 | data.MAX_TOKEN = parseInt(data.MAX_TOKEN) 59 | 60 | if(!data.MAX_TOKEN){ 61 | data.MAX_TOKEN = 1000 62 | } 63 | 64 | let res = await fetch("/api/config", { 65 | method: "POST", 66 | credentials: "include", 67 | body: JSON.stringify(data), 68 | headers: { 69 | "Content-Type": "application/json", 70 | } 71 | }) 72 | 73 | if(res.status != 200){ 74 | // Show the notification 75 | Failure.style.display = "block"; 76 | 77 | // Hide the notification after some time (optional) 78 | setTimeout(() => { 79 | Failure.style.display = "none"; 80 | }, 5000); // Hide after 5 seconds 81 | return; 82 | } 83 | await loadConfig() 84 | // Show the notification 85 | Success.style.display = "block"; 86 | 87 | // Hide the notification after some time (optional) 88 | setTimeout(() => { 89 | Success.style.display = "none"; 90 | }, 5000); // Hide after 5 seconds 91 | } 92 | 93 | loadConfig() -------------------------------------------------------------------------------- /dashboard/public/js/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/c3c58decfbf3ed107884a4b1cb2027535a0b8dd4/dashboard/public/js/index.js -------------------------------------------------------------------------------- /dashboard/public/js/jquery-3.6.0.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 { 3 | const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0); 4 | 5 | if ($navbarBurgers.length > 0) { 6 | $navbarBurgers.forEach( el => { 7 | el.addEventListener('click', () => { 8 | const target = el.dataset.target; 9 | const $target = document.getElementById(target); 10 | el.classList.toggle('is-active'); 11 | $target.classList.toggle('is-active'); 12 | }); 13 | }); 14 | } 15 | }); 16 | 17 | $(document).ready(function() { 18 | $(".navbar-burger").click(function() { 19 | $(".navbar-burger").toggleClass("is-active"); 20 | $(".navbar-menu").toggleClass("is-active"); 21 | }); 22 | }); 23 | 24 | 25 | 26 | // navbar on scroll 27 | $(function () { 28 | $(window).on("scroll", function () { 29 | if ($(window).scrollTop() > 700) { 30 | $("nav").addClass("nav-w"); 31 | $(".navbar-menu").addClass("nav-w"); 32 | $(".navbar-item").addClass("nav-dark"); 33 | $(".navbar-link").addClass("nav-dark"); 34 | $(".navbar-burger").removeClass("has-text-white"); 35 | $(".navbar-burger").addClass("has-text-dark"); 36 | } else { 37 | $("nav").removeClass("nav-w"); 38 | $(".navbar-menu").removeClass("nav-w"); 39 | $(".navbar-item").removeClass("nav-dark"); 40 | $(".navbar-link").removeClass("nav-dark"); 41 | $(".navbar-burger").removeClass("has-text-dark"); 42 | $(".navbar-burger").addClass("has-text-white"); 43 | } 44 | }); 45 | }); 46 | 47 | // back to top 48 | var btn = $("#backtotop"); 49 | 50 | $(window).scroll(function () { 51 | if ($(window).scrollTop() > 100) { 52 | btn.addClass("show"); 53 | } else { 54 | btn.removeClass("show"); 55 | } 56 | }); 57 | 58 | btn.on("click", function (e) { 59 | e.preventDefault(); 60 | $("html, body").animate({ scrollTop: 0 }, "300"); 61 | }); 62 | 63 | // copyright year 64 | document.getElementById("cp-year").innerHTML = new Date().getFullYear() 65 | 66 | const Succ = document.getElementById("notiSuccess"); 67 | const Fail = document.getElementById("notiFail"); 68 | const deleteButton1 = Succ.querySelector(".delete"); 69 | const deleteButton2 = Fail.querySelector(".delete"); 70 | 71 | deleteButton1.addEventListener("click", () => { 72 | // Hide the notification when the delete button is clicked 73 | Succ.style.display = "none"; 74 | }); 75 | deleteButton2.addEventListener("click", () => { 76 | // Hide the notification when the delete button is clicked 77 | Fail.style.display = "none"; 78 | }); -------------------------------------------------------------------------------- /dashboard/routes/api.js: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import jwt from "jsonwebtoken"; 3 | 4 | import config from '../../config/config.js' 5 | import { JWT_SECRET } from "../dasboard.js"; 6 | import auth from "../middleware/auth.js"; 7 | 8 | const API_ROUTER = Router() 9 | 10 | API_ROUTER.post("/login", (req, res) => { 11 | if (process.env.DASHBOARD_USERNAME == req.body.username && 12 | process.env.DASHBOARD_PASSWORD == req.body.password) { 13 | 14 | jwt.sign({ 15 | data: 'foobar' 16 | }, JWT_SECRET, { expiresIn: '1h' },(err,token)=>{ 17 | 18 | res.cookie("auth", token, { 19 | maxAge: 1000 * 60 * 60, 20 | httpOnly: true 21 | }) 22 | res.redirect("/dashboard.html") 23 | }); 24 | return; 25 | } 26 | res.redirect("/") 27 | }) 28 | 29 | API_ROUTER.get("/checkauth",auth, (req, res) => { 30 | res.sendStatus(200) 31 | }) 32 | 33 | API_ROUTER.get("/config",auth,(req,res)=>{ 34 | res.send(config.getFullConfig()) 35 | }) 36 | 37 | API_ROUTER.post("/config",auth,(req,res)=>{ 38 | let data = req.body 39 | let keys = Object.keys(data) 40 | 41 | if(data.MAX_TOKEN != undefined){ 42 | data.MAX_TOKEN = parseInt(data.MAX_TOKEN) 43 | if(!data.MAX_TOKEN){ 44 | data.MAX_TOKEN = 1000 45 | } 46 | } 47 | 48 | keys.forEach((key)=>{ 49 | config.set(key,data[key]) 50 | }) 51 | config.save() 52 | res.sendStatus(200) 53 | }) 54 | 55 | API_ROUTER.get("/oauthurl",auth,(req,res)=>{ 56 | res.send({ 57 | url:`https://discord.com/api/oauth2/authorize?client_id=${process.env.DISCORD_CLIENT_ID}&permissions=2147486720&scope=bot` 58 | }) 59 | }) 60 | 61 | export default API_ROUTER -------------------------------------------------------------------------------- /discord/discord_commands.js: -------------------------------------------------------------------------------- 1 | import { REST, Routes } from 'discord.js' 2 | 3 | import stableDiffusion from '../huggingface/stablediffusion/stableDiffusion.js'; 4 | import instructPix2pix from '../huggingface/instruct-pix2pix/instruct-pix2pix.js'; 5 | import { askQuestion } from '../chatgpt/chatgpt.js'; 6 | import { generateInteractionReply, createEmbedsForImageCommand, createEmbedForRemixCommand } from './discord_helpers.js'; 7 | 8 | export const commands = [ 9 | { 10 | name: 'ask', 11 | description: 'Ask Anything!', 12 | options: [ 13 | { 14 | name: "question", 15 | description: "Your question", 16 | type: 3, 17 | required: true 18 | }, 19 | { 20 | name: "image", 21 | description: "Generate an image ?", 22 | type: 3, 23 | choices: [ 24 | { 25 | name: "Yes", 26 | value: "true" 27 | }, 28 | { 29 | name: "No", 30 | value: "false" 31 | } 32 | ] 33 | } 34 | ] 35 | }, 36 | { 37 | name: 'image', 38 | description: 'Ask Anything!', 39 | options: [ 40 | { 41 | name: "prompt", 42 | description: "Your prompt", 43 | type: 3, 44 | required: true 45 | } 46 | ] 47 | }, 48 | { 49 | name: 'remix', 50 | description: 'Remix', 51 | options: [ 52 | { 53 | name: "user", 54 | description: "user", 55 | type: 3, 56 | required: true 57 | }, 58 | { 59 | name: "prompt", 60 | description: "Your prompt", 61 | type: 3, 62 | required: true 63 | } 64 | ] 65 | }, 66 | ]; 67 | 68 | export async function initDiscordCommands() { 69 | const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_BOT_TOKEN); 70 | 71 | try { 72 | console.log('Started refreshing application (/) commands.'); 73 | await rest.put(Routes.applicationCommands(process.env.DISCORD_CLIENT_ID), { body: commands }); 74 | console.log('Successfully reloaded application (/) commands.'); 75 | } catch (error) { 76 | console.error(error); 77 | } 78 | } 79 | 80 | export async function handle_interaction_ask(interaction) { 81 | const user = interaction.user 82 | 83 | // Begin conversation 84 | const question = interaction.options.getString("question") 85 | const generateImage = interaction.options.getString("image") == "true" ? true : false; 86 | await interaction.deferReply() 87 | 88 | try { 89 | askQuestion(question, async (content) => { 90 | generateInteractionReply(interaction, user, question, generateImage, content) 91 | }) 92 | } catch (e) { 93 | console.error(e) 94 | } 95 | } 96 | 97 | export async function handle_interaction_image(interaction) { 98 | const user = interaction.user 99 | const prompt = interaction.options.getString("prompt") 100 | try { 101 | await interaction.deferReply() 102 | stableDiffusion.generate(prompt, async (result) => { 103 | if (result.error) { 104 | await interaction.editReply({ content: "error..." }).catch(() => { }) 105 | return; 106 | } 107 | 108 | try { 109 | let embeds = createEmbedsForImageCommand(user, prompt, result.results) 110 | await interaction.editReply(embeds).catch(() => { }) 111 | } catch (e) { 112 | console.log(e) 113 | await interaction.editReply({ content: "error..." }).catch(() => { }) 114 | } 115 | 116 | }) 117 | } catch (e) { 118 | console.error(e) 119 | } 120 | } 121 | 122 | export async function handle_interaction_remix(interaction, client) { 123 | await interaction.deferReply() 124 | 125 | const user = interaction.user 126 | const prompt = interaction.options.getString("prompt") 127 | let user_remix_id = interaction.options.getString("user") 128 | const regex = /^<@(\d+)>$/ 129 | 130 | user_remix_id = regex.exec(user_remix_id) 131 | 132 | if (!user_remix_id) { 133 | return; 134 | } 135 | 136 | user_remix_id = user_remix_id[1] 137 | 138 | try { 139 | const user_remix = await client.users.fetch(user_remix_id) 140 | let pp_url = user_remix.displayAvatarURL() 141 | pp_url = pp_url.split(".") 142 | pp_url[pp_url.length - 1] = "jpg" 143 | pp_url = pp_url.join(".") 144 | 145 | const pp = await fetch(pp_url) 146 | const pp_blob = await pp.blob() 147 | const pp_buffer = Buffer.from(await pp_blob.arrayBuffer()) 148 | const pp_base64 = "data:image/jpg;base64," + pp_buffer.toString("base64") 149 | 150 | instructPix2pix.remix(pp_base64, prompt, async (res) => { 151 | if (res.error) { 152 | await interaction.editReply({ content: "error..." }).catch(() => { }) 153 | return; 154 | } 155 | 156 | let embed = createEmbedForRemixCommand( 157 | user, 158 | user_remix, 159 | prompt, 160 | res.image 161 | ) 162 | 163 | await interaction.editReply({ 164 | content: interaction.options.getString("user"), 165 | ...embed 166 | }).catch(() => { }) 167 | }) 168 | 169 | 170 | } catch (e) { 171 | console.error(e) 172 | } 173 | } 174 | 175 | export const commandExecuters = { 176 | ask: handle_interaction_ask, 177 | image: handle_interaction_image, 178 | remix: handle_interaction_remix 179 | } -------------------------------------------------------------------------------- /discord/discord_helpers.js: -------------------------------------------------------------------------------- 1 | import { EmbedBuilder, AttachmentBuilder } from 'discord.js' 2 | 3 | import stableDiffusion from '../huggingface/stablediffusion/stableDiffusion.js'; 4 | import config from '../config/config.js'; 5 | 6 | export const MAX_RESPONSE_CHUNK_LENGTH = 1500 7 | 8 | export function createEmbedForAskCommand(user, prompt, response) { 9 | 10 | if (prompt.length >= 250) { 11 | prompt = prompt.slice(0, 250) + "..." 12 | } 13 | 14 | const embed = new EmbedBuilder() 15 | .setColor(0x0099FF) 16 | .setAuthor({ name: user.username }) 17 | .setTitle(prompt) 18 | .setDescription(response.slice(0, Math.min(response.length, 4096))) 19 | 20 | if (response.length > 4096) { 21 | response = response.slice(4096, response.length) 22 | for (let i = 0; i < 10 && response.length > 0; i++) { 23 | embed.addFields({ 24 | name: "", 25 | value: response.slice(0, Math.min(response.length, 1024)) 26 | }) 27 | response = response.slice(Math.min(response.length, 1024), response.length) 28 | } 29 | } 30 | 31 | return embed 32 | } 33 | 34 | export function createEmbedsForImageCommand(user, prompt, images) { 35 | let embeds = [] 36 | let files = [] 37 | 38 | if (prompt.length >= 250) { 39 | prompt = prompt.slice(0, 250) + "..." 40 | } 41 | 42 | if (images.length == 0) { 43 | embeds.push( 44 | new EmbedBuilder() 45 | .setColor(0x0099FF) 46 | .setAuthor({ name: user.username }) 47 | .setTitle(prompt) 48 | .setDescription("Image didn't generated for this prompt 😔") 49 | ) 50 | } 51 | 52 | for (let i = 0; i < images.length; i++) { 53 | const image = images[i]; 54 | let embed = new EmbedBuilder().setURL("https://onuryildiz.dev") 55 | 56 | if (i == 0) { 57 | embed.setColor(0x0099FF) 58 | .setAuthor({ name: user.username }) 59 | .setTitle(prompt) 60 | } 61 | 62 | let data = image.split(",")[1] 63 | const buffer = Buffer.from(data, "base64") 64 | 65 | let attachment = new AttachmentBuilder(buffer, { name: `result${i}.jpg` }) 66 | embed.setImage(`attachment://result${i}.jpg`) 67 | 68 | embeds.push(embed) 69 | files.push(attachment) 70 | } 71 | 72 | return { 73 | embeds, 74 | files 75 | } 76 | 77 | } 78 | 79 | export function createEmbedForRemixCommand(user, userRemix, prompt, image) { 80 | 81 | if (prompt.length >= 250) { 82 | prompt = prompt.slice(0, 250) + "..." 83 | } 84 | 85 | const embed = new EmbedBuilder() 86 | .setColor(0x0099FF) 87 | .setAuthor({ name: `${user.username} remixed ${userRemix.username}` }) 88 | .setTitle(prompt) 89 | 90 | let data = image.split(",")[1] 91 | const buffer = Buffer.from(data, "base64") 92 | let attachment = new AttachmentBuilder(buffer, { name: "result0.jpg" }) 93 | embed.setImage("attachment://result0.jpg") 94 | 95 | return { 96 | embeds:[embed], 97 | files:[attachment] 98 | } 99 | } 100 | 101 | export async function splitAndSendResponse(resp, user) { 102 | let tryCount = 3; 103 | while (resp.length > 0 && tryCount > 0) { 104 | try { 105 | let end = Math.min(MAX_RESPONSE_CHUNK_LENGTH, resp.length) 106 | await user.send(resp.slice(0, end)) 107 | resp = resp.slice(end, resp.length) 108 | } catch (e) { 109 | tryCount-- 110 | console.error("splitAndSendResponse Error : " + e + " | Counter " + tryCount) 111 | } 112 | } 113 | 114 | if (tryCount <= 0) { 115 | throw "Failed to send dm." 116 | } 117 | } 118 | 119 | export async function generateInteractionReply(interaction, user, question, generateImage, content) { 120 | if (config.get("USE_EMBED")) { 121 | //embed 122 | const embed = createEmbedForAskCommand(user, question, content) 123 | await interaction.editReply({ embeds: [embed] }).catch(() => { }) 124 | if(generateImage) { 125 | let stableDiffusionPrompt = content.slice(0, Math.min(content.length, 200)) 126 | stableDiffusion.generate(stableDiffusionPrompt, async (result) => { 127 | const results = result.results 128 | if (!results || results.length == 0) { 129 | return; 130 | } 131 | let data = result.results[0].split(",")[1] 132 | const buffer = Buffer.from(data, "base64") 133 | let attachment = new AttachmentBuilder(buffer, { name: "result0.jpg" }) 134 | embed.setImage("attachment://result0.jpg") 135 | await interaction.editReply({ embeds: [embed], files: [attachment] }).catch(() => { }) 136 | }) 137 | } 138 | } else { 139 | //normal message 140 | if (content.length >= MAX_RESPONSE_CHUNK_LENGTH) { 141 | const attachment = new AttachmentBuilder(Buffer.from(content, 'utf-8'), { name: 'response.txt' }); 142 | await interaction.editReply({ files: [attachment] }).catch(() => { }) 143 | } else { 144 | await interaction.editReply({ content }).catch(() => { }) 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /huggingface/huggingface_ws.js: -------------------------------------------------------------------------------- 1 | import WebSocket from 'ws'; 2 | 3 | function generateHash() { 4 | const chars = "qwertyuopasdfghjklizxcvbnm0123456789" 5 | let hash = "" 6 | for (let i = 0; i < 11; i++) { 7 | hash += chars[Math.floor(Math.random() * chars.length)] 8 | } 9 | return { 10 | session_hash: hash, 11 | fn_index: 2 12 | } 13 | } 14 | 15 | function request(API_URL,userData, callback,opts={}, tryCount=5) { 16 | const client = new WebSocket(API_URL); 17 | const hash = generateHash() 18 | 19 | let tmr = setTimeout(() => { 20 | client.close() 21 | callback({ 22 | error: true 23 | }) 24 | }, 10 * 60 * 1000); 25 | 26 | client.on("open", () => { 27 | 28 | }) 29 | 30 | client.on("error",(err)=>{ 31 | console.log(err) 32 | callback({ 33 | error:true, 34 | }) 35 | }) 36 | 37 | client.on("message", (message) => { 38 | let msg = JSON.parse("" + message) 39 | 40 | if (msg.msg == "send_hash") { 41 | client.send(JSON.stringify(hash)) 42 | } else if (msg.msg == "send_data") { 43 | let data = { 44 | data: userData, 45 | ...hash, 46 | ...opts 47 | } 48 | client.send(JSON.stringify(data)) 49 | } else if (msg.msg == "process_completed") { 50 | clearTimeout(tmr) 51 | try{ 52 | const results = msg.output.data 53 | callback({ 54 | error:false, 55 | results 56 | }) 57 | }catch(e){ 58 | callback({ 59 | error:true, 60 | }) 61 | } 62 | 63 | }else if(msg.msg == "queue_full"){ 64 | if(tryCount <= 0){ 65 | callback({ 66 | error:true, 67 | }) 68 | }else{ 69 | setTimeout(()=>{ 70 | request(API_URL,userData,callback,opts,tryCount-1) 71 | },5000) 72 | } 73 | } 74 | 75 | }) 76 | } 77 | 78 | export default { 79 | request 80 | } -------------------------------------------------------------------------------- /huggingface/instruct-pix2pix/instruct-pix2pix.js: -------------------------------------------------------------------------------- 1 | import huggingface_ws from "../huggingface_ws.js" 2 | 3 | const API_URL = "wss://timbrooks-instruct-pix2pix.hf.space/queue/join" 4 | 5 | function remix(image, prompt, cb) { 6 | const userData = [ 7 | image, 8 | prompt, 9 | 50, 10 | "Randomize Seed", 11 | 22892, 12 | "Fix CFG", 13 | 7.5, 14 | 1.5 15 | ] 16 | 17 | huggingface_ws.request(API_URL, userData, (res) => { 18 | if (res.error) { 19 | cb({ 20 | error: true 21 | }) 22 | } else { 23 | const image = res.results[3] 24 | cb({ 25 | error: false, 26 | image 27 | }) 28 | } 29 | }, { fn_index: 1 }) 30 | } 31 | 32 | export default { 33 | remix 34 | } -------------------------------------------------------------------------------- /huggingface/stablediffusion/stableDiffusion.js: -------------------------------------------------------------------------------- 1 | import huggingface_ws from "../huggingface_ws.js" 2 | 3 | const API_URL = "wss://runwayml-stable-diffusion-v1-5.hf.space/queue/join" 4 | 5 | function generate(prompt, cb) { 6 | const userData = [prompt] 7 | 8 | huggingface_ws.request(API_URL, userData, (res) => { 9 | if (res.error) { 10 | cb({ 11 | error: true 12 | }) 13 | } else { 14 | const results = res.results[0] 15 | cb({ 16 | error: false, 17 | results 18 | }) 19 | } 20 | }) 21 | } 22 | 23 | export default { 24 | generate 25 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import 'dotenv/config' 2 | import { Client, GatewayIntentBits, Partials, ChannelType } from 'discord.js' 3 | 4 | import config from './config/config.js' 5 | import { askQuestion } from './chatgpt/chatgpt.js' 6 | import { initDiscordCommands, handle_interaction_ask, handle_interaction_image, handle_interaction_remix, commandExecuters } from './discord/discord_commands.js' 7 | import { splitAndSendResponse, MAX_RESPONSE_CHUNK_LENGTH } from './discord/discord_helpers.js' 8 | import { initDashboard } from './dashboard/dasboard.js' 9 | 10 | async function main() { 11 | await initDiscordCommands() 12 | initDashboard() 13 | 14 | const client = new Client({ 15 | intents: [ 16 | GatewayIntentBits.Guilds, 17 | GatewayIntentBits.GuildMessages, 18 | GatewayIntentBits.GuildIntegrations, 19 | GatewayIntentBits.DirectMessages, 20 | GatewayIntentBits.DirectMessageTyping, 21 | GatewayIntentBits.MessageContent 22 | ], 23 | partials: [Partials.Channel] 24 | }); 25 | 26 | client.on('ready', () => { 27 | console.log(`Logged in as ${client.user.tag}!`); 28 | console.log(new Date()) 29 | }); 30 | 31 | client.on("messageCreate", async message => { 32 | if (config.get("ENABLE_DIRECT_MESSAGES") !== true || message.channel.type != ChannelType.DM || message.author.bot) { 33 | return; 34 | } 35 | const user = message.author 36 | 37 | console.log("----Direct Message---") 38 | console.log("Date : " + new Date()) 39 | console.log("UserId : " + user.id) 40 | console.log("User : " + user.username) 41 | console.log("Message : " + message.content) 42 | console.log("--------------") 43 | 44 | try { 45 | let sentMessage = await user.send("Hmm, let me think...") 46 | askQuestion(message.content, async (response) => { 47 | if (response.length >= MAX_RESPONSE_CHUNK_LENGTH) { 48 | splitAndSendResponse(response, user) 49 | } else { 50 | await sentMessage.edit(response) 51 | } 52 | }) 53 | } catch (e) { 54 | console.error(e) 55 | } 56 | }) 57 | 58 | client.on("interactionCreate", async interaction => { 59 | if(commandExecuters[interaction.commandName]){ 60 | commandExecuters[interaction.commandName](interaction,client) 61 | } 62 | }); 63 | 64 | client.login(process.env.DISCORD_BOT_TOKEN); 65 | } 66 | 67 | main() 68 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Onur YILDIZ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chatgpt-discordjs", 3 | "version": "1.0.9", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "nodemonConfig": { 8 | "ignore": [ 9 | "configFile/config.json" 10 | ] 11 | }, 12 | "scripts": { 13 | "dev": "nodemon index.js", 14 | "start": "node index.js" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "ISC", 19 | "dependencies": { 20 | "body-parser": "^1.20.2", 21 | "cheerio": "^1.0.0-rc.12", 22 | "cookie-parser": "^1.4.6", 23 | "discord.js": "^14.11.0", 24 | "dotenv": "^16.0.3", 25 | "express": "^4.18.2", 26 | "gpt-3-encoder": "^1.1.4", 27 | "https-proxy-agent": "^5.0.1", 28 | "jsonwebtoken": "^9.0.0", 29 | "node-fetch": "^3.3.1", 30 | "proxy-check": "^1.0.8", 31 | "ws": "^8.11.0" 32 | }, 33 | "devDependencies": { 34 | "nodemon": "^2.0.20" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /proxyService/freeProxyList.js: -------------------------------------------------------------------------------- 1 | import * as cheerio from 'cheerio'; 2 | 3 | let mem = { 4 | proxies:[], 5 | date: 0 6 | } 7 | 8 | export async function getProxies(opts = { 9 | params: "port=&type%5B%5D=http&type%5B%5D=https&speed%5B%5D=3&up_time=50", 10 | bannedCountries: ["China","Colombia"] 11 | }) { 12 | 13 | let bannedCountriesMap = {} 14 | for(let i=0;i tbody > tr") 29 | for (let i = 0; i < rows.length; i++) { 30 | const row = rows[i] 31 | const columns = $(row).find("td") 32 | const proxy = { 33 | ip: $(columns[0]).text(), 34 | port: $(columns[2]).text(), 35 | country: $(columns[3])?.text()?.trim(), 36 | speedDownload: parseInt($(columns[5]).text()), 37 | connectTimes: parseFloat($(columns[6]).text()), 38 | upTime: parseInt($(columns[7]).text()) || 0, 39 | type: $(columns[8])?.text()?.trim(), 40 | anon: $(columns[9])?.text()?.trim(), 41 | lastUpdate: $(columns[10])?.text()?.trim() 42 | } 43 | 44 | if(bannedCountriesMap[proxy.country]){ 45 | continue; 46 | } 47 | 48 | proxies.push(proxy) 49 | } 50 | 51 | const pager = $(".content-list-pager")[0] 52 | const pageButtons = $(pager).find("li") 53 | 54 | maxPage = Math.max(parseInt($(pageButtons[pageButtons.length-3]).text()),maxPage) 55 | 56 | } 57 | 58 | mem.proxies = proxies 59 | mem.date = Date.now() 60 | 61 | return proxies 62 | } -------------------------------------------------------------------------------- /proxyService/proxyService.js: -------------------------------------------------------------------------------- 1 | import proxyCheck from 'proxy-check' 2 | import { getProxies } from './freeProxyList.js'; 3 | 4 | export async function getProxy() { 5 | let found = false 6 | return new Promise(async (res, rej) => { 7 | let proxyListToCheck = await getProxies() 8 | 9 | async function checkProxy() { 10 | if (found) { 11 | return; 12 | } 13 | if (proxyListToCheck.length == 0) { 14 | return rej("no proxy found") 15 | } 16 | let proxy = proxyListToCheck.splice(Math.floor(Math.random() * proxyListToCheck.length), 1)[0] 17 | try { 18 | await proxyCheck(`${proxy.ip}:${proxy.port}`) 19 | found = true 20 | res(proxy) 21 | } catch (e) { 22 | checkProxy() 23 | } 24 | } 25 | 26 | for (let i = 0; i < 10; i++) { 27 | checkProxy() 28 | } 29 | 30 | }) 31 | } -------------------------------------------------------------------------------- /screen_shot/Screenshot_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/c3c58decfbf3ed107884a4b1cb2027535a0b8dd4/screen_shot/Screenshot_1.jpg -------------------------------------------------------------------------------- /screen_shot/Screenshot_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/c3c58decfbf3ed107884a4b1cb2027535a0b8dd4/screen_shot/Screenshot_2.jpg -------------------------------------------------------------------------------- /screen_shot/Screenshot_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/c3c58decfbf3ed107884a4b1cb2027535a0b8dd4/screen_shot/Screenshot_3.jpg -------------------------------------------------------------------------------- /screen_shot/Screenshot_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/c3c58decfbf3ed107884a4b1cb2027535a0b8dd4/screen_shot/Screenshot_4.jpg -------------------------------------------------------------------------------- /screen_shot/Screenshot_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/c3c58decfbf3ed107884a4b1cb2027535a0b8dd4/screen_shot/Screenshot_5.jpg -------------------------------------------------------------------------------- /screen_shot/Screenshot_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onury5506/Discord-ChatGPT-Bot/c3c58decfbf3ed107884a4b1cb2027535a0b8dd4/screen_shot/Screenshot_6.jpg --------------------------------------------------------------------------------