7 Commits

Author SHA1 Message Date
2e39587d3c Add gitea actions 2023-07-13 15:08:34 +02:00
edb3f22044 Switching to Earthfile 2023-06-07 21:11:05 +02:00
791b601dec Increase delay between checks to 15 minutes
All checks were successful
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build is passing
2023-04-26 20:03:27 +02:00
1082dd7a71 Fix bug
All checks were successful
continuous-integration/drone/tag Build is passing
2023-04-26 19:58:59 +02:00
96d457ab11 Add small UX improvements
All checks were successful
continuous-integration/drone/tag Build is passing
2023-04-26 19:53:45 +02:00
a2a352efe0 Remove logs
All checks were successful
continuous-integration/drone/tag Build is passing
continuous-integration/drone/push Build is passing
2023-04-26 19:48:59 +02:00
7647399159 Add timeout to fetching posts 2023-04-26 19:48:27 +02:00
7 changed files with 174 additions and 48 deletions

36
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,36 @@
# .github/workflows/ci.yml
name: CI
on:
push:
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
env:
MY_DOCKER_USERNAME: ${{ secrets.MY_DOCKER_USERNAME }}
MY_DOCKER_PASSWORD: ${{ secrets.MY_DOCKER_PASSWORD }}
FORCE_COLOR: 1
steps:
- uses: https://github.com/earthly/actions-setup@v1
with:
version: v0.7.0
- uses: actions/checkout@v2
- name: Put back the git branch into git (Earthly uses it for tagging)
run: |
branch=""
if [ -n "$GITHUB_HEAD_REF" ]; then
branch="$GITHUB_HEAD_REF"
else
branch="${GITHUB_REF##*/}"
fi
git checkout -b "$branch" || true
- name: Docker Login
run: docker login git.hibas.dev --username "$MY_DOCKER_USERNAME" --password "$MY_DOCKER_PASSWORD"
- name: Earthly version
run: earthly --version
- name: Run build
run: earthly --push +docker-multi

View File

@ -1,32 +0,0 @@
FROM node:19 as builder
RUN mkdir -p /app
WORKDIR /app
COPY ["package.json", "yarn.lock", ".yarnrc.yml", "tsconfig.json", "/app/"]
COPY [".yarn", "/app/.yarn"]
COPY ["src", "/app/src"]
RUN yarn install
RUN yarn build
FROM node:19
LABEL maintainer="Fabian Stamm <dev@fabianstamm.de>"
RUN mkdir -p /app
WORKDIR /app
ENV NODE_ENV=production
COPY ["package.json", "yarn.lock", ".yarnrc.yml", "/app/"]
COPY [".yarn", "/app/.yarn"]
RUN yarn install
COPY --from=builder /app/lib/ /app/lib
VOLUME [ "/app/logs", "/app/persist"]
CMD ["node", "lib/index.js"]

19
Earthfile Normal file
View File

@ -0,0 +1,19 @@
VERSION 0.7
FROM node:lts-alpine3.18
WORKDIR /build
docker-multi:
BUILD --platform linux/amd64 --platform linux/arm64 +docker
docker:
COPY package.json yarn.lock .yarnrc.yml tsconfig.json .
COPY src ./src
COPY .yarn ./.yarn
RUN ls -l
RUN yarn install
RUN yarn build
WORKDIR /build
ENTRYPOINT ["node", "lib/index.js"]
ARG EARTHLY_TARGET_TAG
ARG TAG=$EARTHLY_TARGET_TAG
SAVE IMAGE --push git.hibas.dev/hibas123/telegram-rss:$TAG

View File

@ -1,6 +1,6 @@
{ {
"name": "rss-telegram-bot", "name": "rss-telegram-bot",
"version": "1.0.8", "version": "2.0.3",
"main": "lib/index.js", "main": "lib/index.js",
"author": "Fabian Stamm <dev@fabianstamm.de>", "author": "Fabian Stamm <dev@fabianstamm.de>",
"license": "MIT", "license": "MIT",
@ -42,4 +42,4 @@
"typeorm": "^0.3.15" "typeorm": "^0.3.15"
}, },
"packageManager": "yarn@3.5.0" "packageManager": "yarn@3.5.0"
} }

View File

@ -41,7 +41,15 @@ function calculateHash(item: RSSFeedItem) {
async function checkFeed(feed: Feed) { async function checkFeed(feed: Feed) {
Logging.info("Fetching feed: %s", feed.url); Logging.info("Fetching feed: %s", feed.url);
let data = await fetch(feed.url).then(res => res.text()); let timeoutSignal = new AbortController();
let to = setTimeout(() => {
Logging.warn("Feed %s fetch timed out", feed.url);
timeoutSignal.abort();
}, 10000);
let data = await fetch(feed.url, {
signal: timeoutSignal.signal
}).then(res => res.text());
clearTimeout(to);
Logging.info("Received Data"); Logging.info("Received Data");
Logging.debug(data); Logging.debug(data);
@ -90,11 +98,12 @@ async function checkFeed(feed: Feed) {
// feed.addItems(newItems); // feed.addItems(newItems);
} }
// const FEED_CHECK_INTERVAL = 1000 * 60 * 60; const FEED_CHECK_INTERVAL = 1000 * 60 * 15;
const FEED_CHECK_INTERVAL = 1000 * 30; // const FEED_CHECK_INTERVAL = 1000 * 30;
export default async function checkFeeds() { export default async function checkFeeds() {
while (true) { while (true) {
Logging.info("Checking for feeds to synchronize");
let feed = await AppDataSource.manager.findOne(Feed, { let feed = await AppDataSource.manager.findOne(Feed, {
where: { where: {
lastCheck: LessThan(new Date(Date.now() - FEED_CHECK_INTERVAL)) lastCheck: LessThan(new Date(Date.now() - FEED_CHECK_INTERVAL))
@ -105,13 +114,18 @@ export default async function checkFeeds() {
}) })
if (!feed) { if (!feed) {
await new Promise(y => setTimeout(y, 1000)); await new Promise(y => setTimeout(y, 10000));
continue; continue;
} }
await checkFeed(feed);
feed.lastCheck = new Date(); feed.lastCheck = new Date();
await AppDataSource.manager.save(feed); await AppDataSource.manager.save(feed);
Promise.resolve().then(async () => {
await checkFeed(feed);
}).catch(err => {
Logging.warn("Error while checking feed: %s", feed.url);
Logging.error(err);
})
} }
} }

78
src/import_old.ts Normal file
View File

@ -0,0 +1,78 @@
import { readFileSync } from "fs";
import { AppDataSource, appDataSourceReady } from "./data_source.js";
import { Feed } from "./models/Feed.js";
import { Post } from "./models/Post.js";
import { User } from "./models/User.js";
interface IOld {
feeds: {
url: string;
oldEntries: string[];
subscriber: number[];
}[];
}
appDataSourceReady.then(async () => {
let old = JSON.parse(readFileSync("./old.json", "utf-8")) as IOld;
for (let feed of old.feeds) {
let f = await AppDataSource.manager.findOne(Feed, {
where: {
url: feed.url
}
})
if (!f) {
f = AppDataSource.manager.create(Feed, {
url: feed.url,
lastCheck: new Date(0),
oldEntries: [],
subscriber: [],
})
await AppDataSource.manager.save(f);
}
for (let oldEntry of feed.oldEntries) {
let existing = await AppDataSource.manager.findOne(Post, {
where: {
feed: f,
hash: oldEntry
}
})
if (!existing) {
let post = AppDataSource.manager.create(Post, {
feed: f,
hash: oldEntry
})
await AppDataSource.manager.save(post);
}
}
for (let subscriber of feed.subscriber) {
let user = await AppDataSource.manager.findOne(User, {
where: {
chatid: subscriber
},
relations: {
feeds: true
}
});
if (!user) {
user = AppDataSource.manager.create(User, {
chatid: subscriber,
feeds: [f],
})
} else {
user.feeds.push(f)
}
await AppDataSource.manager.save(user);
}
}
})

View File

@ -62,26 +62,37 @@ bot.command("delete", botHandler(async ctx => {
})); }));
bot.on("callback_query", botHandler(async ctx => { bot.on("callback_query", botHandler(async ctx => {
Logging.info("Callback Query:"); Logging.info("Callback Query received");
Logging.info(ctx.callbackQuery);
const remove_options = () => { const remove_options = (message: string) => {
ctx.editMessageReplyMarkup({ ctx.editMessageReplyMarkup({
inline_keyboard: [] inline_keyboard: [],
}) })
ctx.editMessageText(message)
} }
let data = (ctx.callbackQuery as any).data; let data = (ctx.callbackQuery as any).data;
if (!data) { if (!data) {
ctx.answerCbQuery("Invalid data"); ctx.answerCbQuery("Invalid data");
remove_options(); remove_options("Delete failed. Invalid data received.");
return return
} }
let [action, id] = data.split(":"); let [action, id] = data.split(":");
if (!action || !id) { if (!action || !id) {
ctx.answerCbQuery("Invalid data"); ctx.answerCbQuery("Invalid data");
remove_options(); remove_options("Delete failed. Invalid data received.");
return
}
let feed = await AppDataSource.manager.findOne(Feed, {
where: {
id: Number(id)
}
});
if (!feed) {
ctx.answerCbQuery("Invalid action");
remove_options("Delete failed. Feed not available.");
return return
} }
@ -101,12 +112,12 @@ bot.on("callback_query", botHandler(async ctx => {
} }
} else { } else {
ctx.answerCbQuery("Invalid action"); ctx.answerCbQuery("Invalid action");
remove_options(); remove_options("Delete failed. Invalid data received.");
return return
} }
ctx.answerCbQuery("Success"); ctx.answerCbQuery("Success");
remove_options(); remove_options("Deleted feed: " + feed.url);
})); }));
bot.on(message("text", "entities"), botHandler(async ctx => { bot.on(message("text", "entities"), botHandler(async ctx => {