Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e0c088fa7 | ||
|
|
43b4757696 | ||
|
|
3c6bdeab60 | ||
|
|
11a26bff83 | ||
|
|
e1cf854d27 | ||
|
|
972ee67f53 | ||
|
|
9ecfdef62b | ||
|
|
e56f0883cf | ||
|
|
5aa69588fb | ||
|
|
28b028d056 | ||
|
|
4ac04d4457 | ||
|
|
9d137b6b52 | ||
|
|
79110bdb1c | ||
|
|
0d2fba3883 | ||
|
|
77aa924161 |
11
dockerfile
11
dockerfile
@@ -1,17 +1,20 @@
|
||||
# Use oven/bun as parent image
|
||||
FROM oven/bun:latest
|
||||
FROM oven/bun:1.0.27
|
||||
|
||||
# Change the working directory on the Docker image to /app
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package.json and package-lock.json to the /app directory
|
||||
COPY . .
|
||||
COPY package.json ./
|
||||
COPY bun.lockb ./
|
||||
COPY src ./src
|
||||
COPY tsconfig.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN bun install
|
||||
RUN bun install --frozen-lockfile
|
||||
|
||||
# Expose application port
|
||||
EXPOSE 3000
|
||||
|
||||
# Start the application
|
||||
CMD bun start
|
||||
CMD ["bun", "start"]
|
||||
69
package.json
69
package.json
@@ -1,35 +1,38 @@
|
||||
{
|
||||
"name": "legica-dana",
|
||||
"version": "2.0.2",
|
||||
"main": "src/app.ts",
|
||||
"scripts": {
|
||||
"start": "bun src/app.ts"
|
||||
},
|
||||
"author": "Fran Jurmanović <fjurma12@outlook.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@elysiajs/cron": "^0.7.0",
|
||||
"@elysiajs/static": "^0.7.1",
|
||||
"@elysiajs/swagger": "^0.7.3",
|
||||
"axios": "^0.26.0",
|
||||
"body-parser": "^1.20.2",
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"dayjs": "^1.11.10",
|
||||
"discord.js": "^12.5.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"elysia": "^0.7.15",
|
||||
"lodash-es": "^4.17.21",
|
||||
"minimatch": "^9.0.3",
|
||||
"pino": "^8.15.4",
|
||||
"typescript": "^4.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash-es": "^4.17.9",
|
||||
"@types/node": "^20.8.2",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
||||
"@typescript-eslint/parser": "^6.7.4",
|
||||
"bun-types": "^1.0.4-canary.20231004T140131",
|
||||
"eslint": "^8.50.0",
|
||||
"prettier": "^2.2.1"
|
||||
}
|
||||
"name": "legica-dana",
|
||||
"version": "2.1.0",
|
||||
"main": "src/app.ts",
|
||||
"scripts": {
|
||||
"start": "bun run src/app.ts",
|
||||
"build-script": "bun build src/app.ts --outdir dist --target bun",
|
||||
"start-build": "bun run dist/app.js"
|
||||
},
|
||||
"author": "Fran Jurmanović <fjurma12@outlook.com>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@elysiajs/cron": "^0.7.0",
|
||||
"@elysiajs/static": "^0.7.1",
|
||||
"@elysiajs/swagger": "^0.7.3",
|
||||
"axios": "^0.26.0",
|
||||
"body-parser": "^1.20.2",
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"dayjs": "^1.11.10",
|
||||
"discord.js": "^12.5.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"elysia": "^0.7.15",
|
||||
"ffmpeg-static": "^5.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"minimatch": "^9.0.3",
|
||||
"pino": "^8.15.4",
|
||||
"typescript": "^4.1.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash-es": "^4.17.9",
|
||||
"@types/node": "^20.8.2",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
||||
"@typescript-eslint/parser": "^6.7.4",
|
||||
"bun-types": "^1.0.4-canary.20231004T140131",
|
||||
"eslint": "^8.50.0",
|
||||
"prettier": "^2.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
57
src/app.ts
57
src/app.ts
@@ -5,7 +5,6 @@ import { Elysia, t } from "elysia";
|
||||
import { swagger } from "@elysiajs/swagger";
|
||||
import { basicAuth, BasicAuthError } from "@core";
|
||||
import pino from "pino";
|
||||
import staticPlugin from "@elysiajs/static";
|
||||
import cron from "@elysiajs/cron";
|
||||
|
||||
const client: Client = new Client();
|
||||
@@ -29,6 +28,55 @@ async function jobRunner() {
|
||||
logger.error(err);
|
||||
}
|
||||
}
|
||||
const botPlugin = new Elysia({ prefix: "/bot" })
|
||||
.use(
|
||||
basicAuth({
|
||||
users: [
|
||||
{
|
||||
username: "admin",
|
||||
password: config.PASSWORD,
|
||||
},
|
||||
],
|
||||
errorMessage: "Unauthorized",
|
||||
})
|
||||
)
|
||||
.get(
|
||||
"/",
|
||||
() => ({
|
||||
uptime: client.uptime,
|
||||
readyAt: client.readyAt,
|
||||
readyTimestamp: client.readyTimestamp,
|
||||
}),
|
||||
{
|
||||
detail: {
|
||||
summary: "Get BOT status",
|
||||
},
|
||||
}
|
||||
)
|
||||
.post(
|
||||
"/",
|
||||
() => {
|
||||
client.login(config.TOKEN);
|
||||
return "Bot logged in started";
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
summary: "Start BOT if it is not running",
|
||||
},
|
||||
}
|
||||
)
|
||||
.delete(
|
||||
"/",
|
||||
() => {
|
||||
client.destroy();
|
||||
return "Bot logged out";
|
||||
},
|
||||
{
|
||||
detail: {
|
||||
summary: "Stops the BOT.",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const taskPlugin = new Elysia({ prefix: "/job" })
|
||||
.use(
|
||||
@@ -138,7 +186,7 @@ const taskPlugin = new Elysia({ prefix: "/job" })
|
||||
"/send",
|
||||
async ({ set, body }) => {
|
||||
try {
|
||||
const url = body.url;
|
||||
const url = body?.url;
|
||||
if (url) {
|
||||
await sendDiscordMessage(client, url);
|
||||
} else {
|
||||
@@ -147,7 +195,8 @@ const taskPlugin = new Elysia({ prefix: "/job" })
|
||||
return true;
|
||||
} catch (err) {
|
||||
set.status = 400;
|
||||
return err;
|
||||
logger.error(err);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -210,8 +259,8 @@ const app = new Elysia()
|
||||
},
|
||||
})
|
||||
)
|
||||
.use(staticPlugin())
|
||||
.use(taskPlugin)
|
||||
.use(botPlugin)
|
||||
.listen(config.PORT);
|
||||
|
||||
client.login(config.TOKEN);
|
||||
|
||||
@@ -2,10 +2,10 @@ import { config } from "@constants";
|
||||
import axios from "axios";
|
||||
import cheerio from "cheerio";
|
||||
|
||||
export async function getFirstHtml(): Promise<string> {
|
||||
export async function getFirstHtml(): Promise<string | undefined> {
|
||||
const response = await axios.get(config.LEGICA_URL);
|
||||
const html = response.data;
|
||||
const $ = cheerio.load(html);
|
||||
const { href } = $(".News-link.c-def")?.attr() || {};
|
||||
const href = $(".legica-dana").first().find("a").attr("href");
|
||||
return href;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,9 @@ export async function getImgTitle(href: string): Promise<Legica> {
|
||||
const html = response.data;
|
||||
const $ = cheerio.load(html);
|
||||
|
||||
const title = $(".Article-inner > h1").text();
|
||||
const { src: img } = $(".Article-media > img").attr() || {};
|
||||
const title = $(".article-title-container > h1").text();
|
||||
const src = $(".image-holder", ".article-content").find("img").attr("src");
|
||||
if (!src) throw new Error(`Image not found at ${href}.`);
|
||||
|
||||
return { title, img };
|
||||
return { title, img: src };
|
||||
}
|
||||
|
||||
@@ -6,17 +6,15 @@ import { Client, MessageEmbed, TextChannel } from "discord.js";
|
||||
|
||||
dayjs.extend(customParseFormat);
|
||||
|
||||
const dateRegex = /\d{1,2}.\d{1,2}.\d{4}/g;
|
||||
|
||||
export async function sendDiscordMessage(
|
||||
client: Client,
|
||||
url: string,
|
||||
dateCheck?: dayjs.Dayjs
|
||||
): Promise<void> {
|
||||
if (!url) return;
|
||||
const { img, title } = await getImgTitle(url);
|
||||
|
||||
if (dateCheck) {
|
||||
const dateRegex = /\d{1,2}.\d{1,2}.\d{4}/g;
|
||||
const date = dateRegex.exec(title)?.[0];
|
||||
const dayjsDate = dayjs(date, config.LEGICA_DATE_FORMAT);
|
||||
if (!dateCheck.isSame(dayjsDate, "D"))
|
||||
@@ -27,7 +25,7 @@ export async function sendDiscordMessage(
|
||||
);
|
||||
}
|
||||
|
||||
client.channels.cache.forEach(async (channel) => {
|
||||
const promises = client.channels.cache.map(async (channel) => {
|
||||
try {
|
||||
if (channel.type !== "text") return null;
|
||||
const embeddedMessage = new MessageEmbed().setTitle(title).setImage(img);
|
||||
@@ -51,13 +49,16 @@ export async function sendDiscordMessage(
|
||||
console.error(`Reaction ${reaction} to channel ${channel.id} failed.`);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
} catch (err) {
|
||||
console.error(`Message to channel ${channel.id} failed.`);
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
export async function sendNextMessage(client: Client): Promise<void> {
|
||||
const href = await getFirstHtml();
|
||||
if (!href) throw new Error("URL cannot be empty!");
|
||||
await sendDiscordMessage(client, href, dayjs());
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ const config: ProjectConfig = {
|
||||
APP_VERSION: version,
|
||||
LEGICA_URL: "https://sib.net.hr/legica-dana",
|
||||
TIMEZONE: process.env.TIMEZONE || "utc",
|
||||
LEGICA_DATE_FORMAT: process.env.LEGICA_DATE_FORMAT || "DD.MM.YYYY",
|
||||
LEGICA_DATE_FORMAT: process.env.LEGICA_DATE_FORMAT || "D.M.YYYY",
|
||||
};
|
||||
|
||||
export { config };
|
||||
|
||||
Reference in New Issue
Block a user