project setup
This commit is contained in:
30
src/bot.ts
Executable file
30
src/bot.ts
Executable file
@@ -0,0 +1,30 @@
|
||||
import { createBot, Intents, startBot } from "npm:discordeno@18.0.1";
|
||||
import * as dotenv from "jsr:@std/dotenv";
|
||||
import { messagehandler } from "./messages.ts";
|
||||
|
||||
const env = dotenv.loadSync();
|
||||
|
||||
if (typeof env.BOT_TOKEN !== "string") {
|
||||
throw new Error("Bot token is required in .env file");
|
||||
}
|
||||
|
||||
const bot = createBot({
|
||||
token: env.BOT_TOKEN,
|
||||
intents: Intents.Guilds | Intents.GuildMessages | Intents.MessageContent |
|
||||
Intents.DirectMessages,
|
||||
events: {
|
||||
ready() {
|
||||
console.log("Bot is ready!");
|
||||
},
|
||||
async messageCreate(bot, message) {
|
||||
await messagehandler(bot, message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Setup desired properties
|
||||
|
||||
|
||||
|
||||
await startBot(bot);
|
||||
|
||||
9
src/logging.ts
Executable file
9
src/logging.ts
Executable file
@@ -0,0 +1,9 @@
|
||||
import * as stdlogger from "jsr:@std/log";
|
||||
import { Message } from "npm:discordeno@18.0.1";
|
||||
|
||||
export function logMessage(message: Message) {
|
||||
return stdlogger.info(
|
||||
`Message from ${message.tag} in ${message.guildId?? "Private"} ${message.channelId} Command:[${message.content}]`
|
||||
);
|
||||
|
||||
}
|
||||
152
src/messages.ts
Executable file
152
src/messages.ts
Executable file
@@ -0,0 +1,152 @@
|
||||
import { Bot, Message } from "npm:discordeno@18.0.1";
|
||||
import { dropdeineMutti, r34test, refresh } from "./r34api.ts";
|
||||
import { logMessage } from "./logging.ts";
|
||||
import { communicate, setMemory } from "./ollama_api.ts";
|
||||
import { dropYandere, dropYandere5, getPage, setPage } from "./yandereapi.ts";
|
||||
import * as dotenv from "jsr:@std/dotenv";
|
||||
|
||||
const env = dotenv.loadSync();
|
||||
const prefix = env.BOT_PREFIX!;
|
||||
|
||||
export async function messagehandler(bot: Bot, message: Message) {
|
||||
const command = message.content.split(" ")[0];
|
||||
const args = message.content.split(" ").slice(1);
|
||||
switch (command) {
|
||||
case `${prefix}rule`:
|
||||
logMessage(message);
|
||||
if (
|
||||
message.channelId === 754338073101205524n ||
|
||||
message.guildId === undefined
|
||||
) {
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: defaultString(await r34test()),
|
||||
});
|
||||
}
|
||||
break;
|
||||
case `${prefix}rule5`:
|
||||
logMessage(message);
|
||||
if (
|
||||
message.channelId === 754338073101205524n ||
|
||||
message.guildId === undefined
|
||||
) {
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: defaultString(await dropdeineMutti()),
|
||||
});
|
||||
}
|
||||
break;
|
||||
case `${prefix}refresh`:
|
||||
logMessage(message);
|
||||
if (
|
||||
message.channelId === 754338073101205524n ||
|
||||
message.guildId === undefined
|
||||
) {
|
||||
await refresh();
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: "Refreshed",
|
||||
});
|
||||
}
|
||||
break;
|
||||
case `${prefix}yande`:
|
||||
logMessage(message);
|
||||
if (
|
||||
message.channelId === 754338073101205524n ||
|
||||
message.guildId === undefined
|
||||
) {
|
||||
await refresh();
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: defaultString(await dropYandere()),
|
||||
});
|
||||
}
|
||||
break;
|
||||
case `${prefix}yande5`:
|
||||
logMessage(message);
|
||||
if (
|
||||
message.channelId === 754338073101205524n ||
|
||||
message.guildId === undefined
|
||||
) {
|
||||
await refresh();
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: defaultString(await dropYandere5()),
|
||||
});
|
||||
}
|
||||
break;
|
||||
case `${prefix}yandepage`:
|
||||
logMessage(message);
|
||||
if (
|
||||
message.channelId === 754338073101205524n ||
|
||||
message.guildId === undefined
|
||||
) {
|
||||
if (args[0] === undefined) {
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: "Please provide a page number",
|
||||
});
|
||||
} else if (isNaN(parseInt(args[0]))) {
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: "Please provide a valid number",
|
||||
});
|
||||
} else {
|
||||
await setPage(parseInt(args[0]));
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: "Page set to " + args[0],
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case `${prefix}yandegetpage`:
|
||||
logMessage(message);
|
||||
if (
|
||||
message.channelId === 754338073101205524n ||
|
||||
message.guildId === undefined
|
||||
) {
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: "Page is " + getPage(),
|
||||
});
|
||||
}
|
||||
break;
|
||||
// TODO Add exception for when the ollama api is down
|
||||
case `${prefix}brainrotgf`:
|
||||
logMessage(message);
|
||||
if (
|
||||
(message.channelId === 754338073101205524n ||
|
||||
message.guildId === undefined) ||
|
||||
message.authorId != 1281272527792111698n
|
||||
) {
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: await communicate("brainrotgf", args.join(" ")),
|
||||
});
|
||||
}
|
||||
break;
|
||||
case `${prefix}brainrotgfmem`:
|
||||
logMessage(message);
|
||||
if (
|
||||
(message.channelId === 754338073101205524n ||
|
||||
message.guildId === undefined) ||
|
||||
message.authorId != 1281272527792111698n
|
||||
) {
|
||||
if (args[0] !== undefined) {
|
||||
const arg = args[0].toLowerCase();
|
||||
if (arg === "true" || arg === "false") {
|
||||
const memoryActive = arg === "true";
|
||||
setMemory(memoryActive);
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: "AI Memory is now set to " + memoryActive,
|
||||
});
|
||||
} else {
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content:
|
||||
"ERROR: Invalid argument. Use true or false.",
|
||||
});
|
||||
}
|
||||
} else {
|
||||
bot.helpers.sendMessage(message.channelId, {
|
||||
content: "Please provide an argument",
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function defaultString(s: string): string {
|
||||
return s === "" ? "ERROR: Tried to send empty message" : s;
|
||||
}
|
||||
101
src/ollama_api.ts
Executable file
101
src/ollama_api.ts
Executable file
@@ -0,0 +1,101 @@
|
||||
import * as dotenv from "jsr:@std/dotenv";
|
||||
|
||||
const env = dotenv.loadSync();
|
||||
const ollamalink: string = env.OLLAMA_API_LINK! + "/api/chat";
|
||||
const ollamaMemoryLimit: number = parseInt(env.OLLAMA_MEMORY_LIMIT!);
|
||||
|
||||
// ATTENTION MEMORY LIMIT IS 10!
|
||||
let memoryActive = false;
|
||||
const memory: Message[] = [];
|
||||
|
||||
type Message = {
|
||||
role: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
type OllamaAPIRequest = {
|
||||
model: string;
|
||||
messages: Message[];
|
||||
stream: boolean;
|
||||
};
|
||||
|
||||
type OllamaAPIResponse = {
|
||||
model: string;
|
||||
created_at: string;
|
||||
message: Message;
|
||||
done: boolean;
|
||||
context: number[];
|
||||
total_duration: number;
|
||||
load_duration: number;
|
||||
prompt_eval_count: number;
|
||||
prompt_eval_duration: number;
|
||||
eval_count: number;
|
||||
eval_duration: number;
|
||||
};
|
||||
|
||||
async function makeRequest(
|
||||
model: string,
|
||||
prompt: string,
|
||||
): Promise<OllamaAPIResponse> {
|
||||
const requestBody: OllamaAPIRequest = {
|
||||
model: model,
|
||||
messages: [
|
||||
...memoryActive ? memory : [],
|
||||
{
|
||||
role: "user",
|
||||
content: prompt,
|
||||
},
|
||||
],
|
||||
stream: false,
|
||||
};
|
||||
|
||||
console.log("Request Body:", JSON.stringify(requestBody));
|
||||
|
||||
try {
|
||||
const response = await fetch(ollamalink, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(requestBody),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data: OllamaAPIResponse = await response.json();
|
||||
console.log("API Response:", data);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error("Error making request:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export function setMemory(tmp: boolean) {
|
||||
memoryActive = tmp;
|
||||
}
|
||||
|
||||
function memoryManager(message: Message) {
|
||||
if (memory.length >= ollamaMemoryLimit) {
|
||||
memory.shift();
|
||||
}
|
||||
memory.push(message);
|
||||
}
|
||||
|
||||
export async function communicate(
|
||||
model: string,
|
||||
prompt: string,
|
||||
): Promise<string> {
|
||||
const response = await makeRequest(model, prompt);
|
||||
memoryManager(
|
||||
{
|
||||
role: "user",
|
||||
content: prompt,
|
||||
},
|
||||
);
|
||||
memoryManager(response.message);
|
||||
console.log("Response:", response);
|
||||
return response.message.content ?? "ERROR: No response";
|
||||
}
|
||||
84
src/r34api.ts
Executable file
84
src/r34api.ts
Executable file
@@ -0,0 +1,84 @@
|
||||
type APIResponse = Array<{
|
||||
preview_url: string;
|
||||
sample_url: string;
|
||||
file_url: string;
|
||||
directory: number;
|
||||
hash: string;
|
||||
width: number;
|
||||
height: number;
|
||||
id: number;
|
||||
image: string;
|
||||
change: number;
|
||||
owner: string;
|
||||
parent_id: number;
|
||||
rating: string;
|
||||
sample: boolean;
|
||||
sample_height: number;
|
||||
sample_width: number;
|
||||
score: number;
|
||||
tags: string;
|
||||
source: string;
|
||||
status: string;
|
||||
has_notes: boolean;
|
||||
comment_count: number;
|
||||
}>;
|
||||
|
||||
// Define the API URL
|
||||
const apiUrl =
|
||||
"https://api.rule34.xxx/index.php?page=dapi&s=post&q=index&json=1";
|
||||
|
||||
// Make a GET request
|
||||
let baseResponse = await fetch(apiUrl, { headers: { "Accept": "application/json" } })
|
||||
.then(async (response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
return <APIResponse> await response.json();
|
||||
});
|
||||
const hyperlinkarray: string[] = [];
|
||||
|
||||
// ---------------------------------
|
||||
// import * as stdHTML from "jsr:@std/html@1.0.2";
|
||||
// Deno.serve({ port: 6969 }, async (request) => {
|
||||
// const html = hyperlinkarray.map((x) => `<img src="${stdHTML.escape(x)}"/>`)
|
||||
// .join("\n");
|
||||
// return new Response(html, {
|
||||
// headers: { "Content-Type": "text/html;charset=utf-8" },
|
||||
// });
|
||||
// });
|
||||
// ---------------------------------
|
||||
|
||||
export async function refresh() {
|
||||
await fetch(apiUrl, { headers: { "Accept": "application/json" } })
|
||||
.then(async (response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
baseResponse = <APIResponse> await response.json();
|
||||
for (const k of baseResponse) {
|
||||
if (!hyperlinkarray.includes(k.file_url)) {
|
||||
hyperlinkarray.push(k.file_url);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (const k of baseResponse) {
|
||||
hyperlinkarray.push(k.file_url);
|
||||
}
|
||||
|
||||
export async function r34test() {
|
||||
if (hyperlinkarray.length === 0) {
|
||||
await refresh();
|
||||
return await r34test();
|
||||
}
|
||||
return hyperlinkarray.pop()!;
|
||||
}
|
||||
|
||||
export async function dropdeineMutti() {
|
||||
let tmp = "";
|
||||
for (let i = 0; i < 5; i++) {
|
||||
tmp += await r34test() + "\n";
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
112
src/yandereapi.ts
Executable file
112
src/yandereapi.ts
Executable file
@@ -0,0 +1,112 @@
|
||||
const apiUrl ="https://yande.re/post.json?api_version=2";
|
||||
|
||||
type APIResponse = {
|
||||
posts: {
|
||||
id: number;
|
||||
tags: string;
|
||||
created_at: string;
|
||||
creator_id: number;
|
||||
approver_id: number;
|
||||
author: string;
|
||||
change: number;
|
||||
source: string;
|
||||
score: number;
|
||||
md5: string;
|
||||
file_size: number;
|
||||
file_ext: string;
|
||||
file_url: string;
|
||||
is_shown_in_index: boolean;
|
||||
preview_url: string;
|
||||
preview_width: number;
|
||||
preview_height: number;
|
||||
actual_preview_width: number;
|
||||
actual_preview_height: number;
|
||||
sample_url: string;
|
||||
sample_width: number;
|
||||
sample_height: number;
|
||||
sample_file_size: number;
|
||||
jpeg_url: string;
|
||||
jpeg_width: number;
|
||||
jpeg_height: number;
|
||||
rating: string;
|
||||
is_rating_locked: boolean;
|
||||
has_children: boolean;
|
||||
parent_id: number;
|
||||
status: string;
|
||||
is_pending: boolean;
|
||||
width: number;
|
||||
height: number;
|
||||
is_held: boolean;
|
||||
frames_pending_string: string;
|
||||
frames_pending: [];
|
||||
frames_string: string;
|
||||
frames: [];
|
||||
is_note_locked: boolean;
|
||||
last_noted_at: string;
|
||||
last_commented_at: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
let page = 1;
|
||||
|
||||
let baseRequest = await fetch(apiUrl, { headers: { "Accept": "application/json" } })
|
||||
.then(async (response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
return <APIResponse> await response.json();
|
||||
});
|
||||
|
||||
|
||||
const hyperlinkarray: string[] = [];
|
||||
for (const k of baseRequest.posts) {
|
||||
hyperlinkarray.push(k.file_url);
|
||||
}
|
||||
|
||||
export function setPage(newpage: number) {
|
||||
page = newpage;
|
||||
hyperlinkarray.length = 0;
|
||||
refresh();
|
||||
}
|
||||
|
||||
export function getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
|
||||
export async function refresh() {
|
||||
await fetch(`${apiUrl}&page=${page}`, { headers: { "Accept": "application/json" } })
|
||||
.then(async (response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
baseRequest = <APIResponse> await response.json();
|
||||
for (const k of baseRequest.posts) {
|
||||
if (!hyperlinkarray.includes(k.file_url)) {
|
||||
hyperlinkarray.push(k.file_url);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchNextPage() {
|
||||
page += 1;
|
||||
await refresh();
|
||||
}
|
||||
|
||||
export async function dropYandere() {
|
||||
if (hyperlinkarray.length === 0) {
|
||||
await fetchNextPage();
|
||||
return await dropYandere();
|
||||
}
|
||||
return hyperlinkarray.pop()!;
|
||||
}
|
||||
|
||||
export async function dropYandere5() {
|
||||
let tmp = "";
|
||||
for (let i = 0; i < 5; i++) {
|
||||
tmp += await dropYandere() + "\n";
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user