Initial commit (untested code)

dnd
Stef Dunlap 2023-03-06 22:30:39 -05:00
parent 9bfe95dfc6
commit a605a3f7be
8 changed files with 20903 additions and 0 deletions

1
.envrc 100644
View File

@ -0,0 +1 @@
use nix

2
.gitignore vendored 100644
View File

@ -0,0 +1,2 @@
config.json
node_modules

20523
LICENSE 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
{
"server": "irc.libera.chat",
"port": 6697,
"nick": "chatgpt",
"channels": ["#chatgpt"],
"openaiApiKey": "[redacted]"
}

78
index.js 100644
View File

@ -0,0 +1,78 @@
#!/usr/bin/env node
//IRC bot that responds to !chat, queries the chatgpt api, and prints the response line by line
const irc = require('irc');
const axios = require('axios');
const config = require('./config.json');
const client = new irc.Client(config.server, config.nick, {
channels: config.channels,
});
// listen for messages that start with !chat and call the chatgpt api with a callback that prints the response line by line
client.addListener('message', async (from, to, message) => {
if (message.startsWith('!chat')) {
const query = message.slice(6);
chatgpt(query, (line) => {
client.say(to, line);
});
}
});
// function that calls the chatgpt streaming api (with server send events) and calls the callback function for each line
function chatgpt(query, callback) {
const apiUrl = 'https://api.openai.com/v1/chat/completions';
const response = await axios.post(apiUrl, {
messages: [{ role: 'user', content: query }],
model: 'gpt-3.5-turbo',
stream: true,
}, {
headers: {
Authorization: `Bearer ${config.openaiApiKey}`,
'Content-Type': 'application/json',
},
responseType: 'stream',
});
let line = '';
response.data.on('data', (event) => {
let data = event.toString();
let parts = data.split('\n');
// parse if starts with data:
for(part of parts) {
if(part === 'data: [DONE]') {
process.stdout.write('\n');
} else if(part.startsWith('data: ')) {
let jsonString = part.slice(part.indexOf('{'), part.lastIndexOf('}') + 1);
try {
let json = JSON.parse(jsonString);
let chunk = json.choices[0].delta.content;
//split the chunk into lines leaving the delimiter in the array
const lines = str.split(/\r?\n/); // split by new lines
let hasStartNewline = str.startsWith("\n");
let hasEndNewline = str.endsWith("\n");
if(hasStartNewline) {
callback(line);
line = '';
}
for (let i = 0; i < lines.length - 1; i++) {
callback(lines[i]);
line = '';
}
line += lines[lines.length - 1];
if(hasEndNewline) {
callback(line);
line = '';
}
} catch (e) {
console.log(e);
console.log(part);
}
}
}
});
}

264
package-lock.json generated 100644
View File

@ -0,0 +1,264 @@
{
"name": "ircgpt",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "ircgpt",
"version": "1.0.0",
"license": "MDGPL",
"dependencies": {
"axios": "^1.3.4",
"irc": "^0.5.2"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/iconv": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/iconv/-/iconv-2.2.3.tgz",
"integrity": "sha512-evIiYeKdt5nEGYKNkQcGPQy781sYgbBKi3gEkt1s4CwteCdOHSjGGRyyp6lP8inYFZwvzG3lgjXEvGUC8nqQ5A==",
"hasInstallScript": true,
"optional": true,
"dependencies": {
"nan": "^2.3.5"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/irc": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/irc/-/irc-0.5.2.tgz",
"integrity": "sha512-KnrvkV05Y71SWmRWHtnlWEIH7LA/YeDul6l7tncCGLNEw4B6Obtmkatb3ACnSLj0kOJ6UBiuhss9e+eRG3zlxw==",
"dependencies": {
"irc-colors": "^1.1.0"
},
"engines": {
"node": ">=0.10.0"
},
"optionalDependencies": {
"iconv": "~2.2.1",
"node-icu-charset-detector": "~0.2.0"
}
},
"node_modules/irc-colors": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/irc-colors/-/irc-colors-1.5.0.tgz",
"integrity": "sha512-HtszKchBQTcqw1DC09uD7i7vvMayHGM1OCo6AHt5pkgZEyo99ClhHTMJdf+Ezc9ovuNNxcH89QfyclGthjZJOw==",
"engines": {
"node": ">=6"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/nan": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==",
"optional": true
},
"node_modules/node-icu-charset-detector": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/node-icu-charset-detector/-/node-icu-charset-detector-0.2.0.tgz",
"integrity": "sha512-DYOFJ3NfKdxEi9hPbmoCss6WydGhJsxpSleUlZfAWEbZt3AU7JuxailgA9tnqQdsHiujfUY9VtDfWD9m0+ThtQ==",
"hasInstallScript": true,
"optional": true,
"dependencies": {
"nan": "^2.3.3"
},
"engines": {
"node": ">=0.6"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
}
},
"dependencies": {
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"axios": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
},
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
},
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
},
"iconv": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/iconv/-/iconv-2.2.3.tgz",
"integrity": "sha512-evIiYeKdt5nEGYKNkQcGPQy781sYgbBKi3gEkt1s4CwteCdOHSjGGRyyp6lP8inYFZwvzG3lgjXEvGUC8nqQ5A==",
"optional": true,
"requires": {
"nan": "^2.3.5"
}
},
"irc": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/irc/-/irc-0.5.2.tgz",
"integrity": "sha512-KnrvkV05Y71SWmRWHtnlWEIH7LA/YeDul6l7tncCGLNEw4B6Obtmkatb3ACnSLj0kOJ6UBiuhss9e+eRG3zlxw==",
"requires": {
"iconv": "~2.2.1",
"irc-colors": "^1.1.0",
"node-icu-charset-detector": "~0.2.0"
}
},
"irc-colors": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/irc-colors/-/irc-colors-1.5.0.tgz",
"integrity": "sha512-HtszKchBQTcqw1DC09uD7i7vvMayHGM1OCo6AHt5pkgZEyo99ClhHTMJdf+Ezc9ovuNNxcH89QfyclGthjZJOw=="
},
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"requires": {
"mime-db": "1.52.0"
}
},
"nan": {
"version": "2.17.0",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz",
"integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==",
"optional": true
},
"node-icu-charset-detector": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/node-icu-charset-detector/-/node-icu-charset-detector-0.2.0.tgz",
"integrity": "sha512-DYOFJ3NfKdxEi9hPbmoCss6WydGhJsxpSleUlZfAWEbZt3AU7JuxailgA9tnqQdsHiujfUY9VtDfWD9m0+ThtQ==",
"optional": true,
"requires": {
"nan": "^2.3.3"
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
}
}
}

19
package.json 100644
View File

@ -0,0 +1,19 @@
{
"name": "ircgpt",
"version": "1.0.0",
"description": "A ChatGPT IRC bot",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"ChatGPT",
"irc"
],
"author": "Stef Dunlap <hello@kindrobot.ca>",
"license": "MDGPL",
"dependencies": {
"axios": "^1.3.4",
"irc": "^0.5.2"
}
}

9
shell.nix 100644
View File

@ -0,0 +1,9 @@
{ pkgs ? import <nixpkgs> {} }:
with pkgs;
mkShell {
buildInputs = [
nodejs
];
}