Skip to content

Commit 47c7505

Browse files
authored
feat: Detect potential reflinks and reply (#78)
1 parent 2d8301e commit 47c7505

File tree

4 files changed

+198
-4
lines changed

4 files changed

+198
-4
lines changed

src/app.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { InvalidUsageError } from './types';
1111
import { getWeekNumber } from './utils';
1212
import { getStatsCollection, initDb } from './db';
1313
import { updateKarmaRoles } from './cron/roles';
14+
import { messageToReflinks } from './commands/reflink';
1415

1516
const MESSAGE_COLLECTOR_CACHE_S = 60 * 60;
1617
const messageCollectorCache = new Cache({ stdTTL: MESSAGE_COLLECTOR_CACHE_S });
@@ -118,6 +119,11 @@ client.on('message', async (msg) => {
118119

119120
void updateMessagesCount(msg.member?.id, msg.member?.displayName).catch(console.error);
120121

122+
const maybeReflinks = messageToReflinks(msg.content);
123+
if (maybeReflinks.length > 0) {
124+
return msg.reply(maybeReflinks);
125+
}
126+
121127
if (/thx|thank|dzięki|dziękuję|dzieki|dziekuje/i.test(msg.content)) {
122128
if (
123129
(thxTimeoutCache.get<Date>(msg.channel.id)?.getTime() ?? 0) <
@@ -187,9 +193,11 @@ client.on('messageDelete', async (msg) => {
187193

188194
async function init() {
189195
await client.login(getConfig('DISCORD_BOT_TOKEN'));
190-
const rssClient = new MonitoRSS.ClientManager(settings);
191-
await new Promise((resolve) => rssClient.start(() => resolve(undefined)));
192-
console.log('MonitoRSS started!');
196+
if (process.env.NODE_ENV === 'production') {
197+
const rssClient = new MonitoRSS.ClientManager(settings);
198+
await new Promise((resolve) => rssClient.start(() => resolve(undefined)));
199+
console.log('MonitoRSS started!');
200+
}
193201
}
194202

195203
init().catch((err) => errors.push(err));

src/commands/mydevil.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const mydevil: Command = {
66
description: 'Wyświetla link do MyDevil.',
77
args: false,
88
execute(msg: Discord.Message) {
9-
return msg.channel.send(`http://www.mydevil.net/pp/9UVOSJRZIV`);
9+
return msg.channel.send(`https://www.mydevil.net/pp/9UVOSJRZIV`);
1010
},
1111
};
1212

src/commands/reflink.spec.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/* eslint no-implicit-dependencies: "off" */
2+
/* eslint no-magic-numbers: "off" */
3+
/* tslint:disable:no-implicit-dependencies no-magic-numbers */
4+
5+
import { expect } from 'chai';
6+
import { helionReflink, xKomReflink } from './reflink';
7+
8+
describe('reflink', () => {
9+
describe('x-kom', () => {
10+
[
11+
[
12+
'https://www.x-kom.pl/p/690347-notebook-laptop-140-apple-macbook-pro-m1-pro-16gb-512-mac-os-space-gray.html',
13+
'https://www.x-kom.pl/p/690347-notebook-laptop-140-apple-macbook-pro-m1-pro-16gb-512-mac-os-space-gray.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&106',
14+
],
15+
[
16+
'https://www.x-kom.pl/p/590802-klawiatura-bezprzewodowa-logitech-mx-keys-for-mac-space-gray.html',
17+
'https://www.x-kom.pl/p/590802-klawiatura-bezprzewodowa-logitech-mx-keys-for-mac-space-gray.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&95',
18+
],
19+
[
20+
'https://www.x-kom.pl/p/523891-monitor-led-27-lg-27ul850-w-4k-hdr.html',
21+
'https://www.x-kom.pl/p/523891-monitor-led-27-lg-27ul850-w-4k-hdr.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&69',
22+
],
23+
[
24+
'https://www.x-kom.pl/p/617252-mikrofon-novox-nc-1-game-box.html',
25+
'https://www.x-kom.pl/p/617252-mikrofon-novox-nc-1-game-box.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&63',
26+
],
27+
[
28+
'https://www.x-kom.pl/p/78034-kamera-internetowa-logitech-c920-pro-full-hd.html',
29+
'https://www.x-kom.pl/p/78034-kamera-internetowa-logitech-c920-pro-full-hd.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&78',
30+
],
31+
[
32+
'https://www.x-kom.pl/p/297064-dysk-sieciowy-nas-macierz-synology-ds216j-2xhdd-2x1ghz-512mb-2xusb-1xlan.html',
33+
'https://www.x-kom.pl/p/297064-dysk-sieciowy-nas-macierz-synology-ds216j-2xhdd-2x1ghz-512mb-2xusb-1xlan.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&107',
34+
],
35+
[
36+
'https://www.x-kom.pl/p/690347-notebook-laptop-140-apple-macbook-pro-m1-pro-16gb-512-mac-os-space-gray.html',
37+
'https://www.x-kom.pl/p/690347-notebook-laptop-140-apple-macbook-pro-m1-pro-16gb-512-mac-os-space-gray.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&106',
38+
],
39+
[
40+
'https://www.x-kom.pl/p/590802-klawiatura-bezprzewodowa-logitech-mx-keys-for-mac-space-gray.html',
41+
'https://www.x-kom.pl/p/590802-klawiatura-bezprzewodowa-logitech-mx-keys-for-mac-space-gray.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&95',
42+
],
43+
[
44+
'https://www.x-kom.pl/p/523891-monitor-led-27-lg-27ul850-w-4k-hdr.html',
45+
'https://www.x-kom.pl/p/523891-monitor-led-27-lg-27ul850-w-4k-hdr.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&69',
46+
],
47+
[
48+
'https://www.x-kom.pl/p/617252-mikrofon-novox-nc-1-game-box.html',
49+
'https://www.x-kom.pl/p/617252-mikrofon-novox-nc-1-game-box.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&63',
50+
],
51+
[
52+
'https://www.x-kom.pl/p/78034-kamera-internetowa-logitech-c920-pro-full-hd.html',
53+
'https://www.x-kom.pl/p/78034-kamera-internetowa-logitech-c920-pro-full-hd.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&78',
54+
],
55+
[
56+
'https://www.x-kom.pl/p/297064-dysk-sieciowy-nas-macierz-synology-ds216j-2xhdd-2x1ghz-512mb-2xusb-1xlan.html',
57+
'https://www.x-kom.pl/p/297064-dysk-sieciowy-nas-macierz-synology-ds216j-2xhdd-2x1ghz-512mb-2xusb-1xlan.html?partnerid=100162370&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd&107',
58+
],
59+
].forEach(([input, expected]) =>
60+
it(`should generate link for ${input}`, () => {
61+
expect(xKomReflink(input)).to.eql(expected);
62+
}),
63+
);
64+
});
65+
66+
describe('helion', () => {
67+
[
68+
[
69+
`https://helion.pl/ksiazki/jezyk-c-i-przetwarzanie-wspolbiezne-w-akcji-wydanie-ii-anthony-williams,jcppw2.htm#format/d`,
70+
`https://helion.pl/view/117666/jcppw2.htm`,
71+
],
72+
73+
[
74+
`https://helion.pl/ksiazki/jak-zarabiac-na-kryptowalutach-wydanie-ii-tomasz-waryszak,jakzk2.htm#format/d`,
75+
`https://helion.pl/view/117666/jakzk2.htm`,
76+
],
77+
[
78+
`https://onepress.pl/ksiazki/sir-ernest-shackleton-i-wyprawa-endurance-sekrety-przywodztwa-odpornego-na-kryzys-adam-staniszewski,sirern.htm#format/d`,
79+
`https://onepress.pl/view/117666/sirern.htm`,
80+
],
81+
[
82+
`https://septem.pl/ksiazki/pietno-morfeusza-k-n-haner,piemor.htm`,
83+
`https://septem.pl/view/117666/piemor.htm`,
84+
],
85+
[
86+
`https://sensus.pl/ksiazki/skutecznosc-gora-mechanizmy-inspiracje-techniki-wplywajace-na-twoje-decyzje-marek-skala,trzyfi.htm#format/d`,
87+
`https://sensus.pl/view/117666/trzyfi.htm`,
88+
],
89+
[
90+
`https://dlabystrzakow.pl/ksiazki/dieta-keto-dla-bystrzakow-rami-abrams-vicky-abrams,dikeby.htm#format/d`,
91+
`https://dlabystrzakow.pl/view/117666/dikeby.htm`,
92+
],
93+
[
94+
`https://bezdroza.pl/ksiazki/szlaki-polski-30-najpiekniejszych-tras-dlugodystansowych-lukasz-supergan,beszpo.htm#format/d`,
95+
`https://bezdroza.pl/view/117666/beszpo.htm`,
96+
],
97+
[
98+
`https://ebookpoint.pl/ksiazki/wojna-w-kosmosie-przewrot-w-geopolityce-jacek-bartosiak-george-friedman,e_25zw.htm#format/e`,
99+
`https://ebookpoint.pl/view/117666/e_25zw.htm`,
100+
],
101+
[
102+
`https://videopoint.pl/kurs/machine-learning-i-jezyk-python-kurs-video-praktyczne-wykorzystanie-popularnych-bibliotek-piotr-szajowski,vprwyp.htm#format/w`,
103+
`https://videopoint.pl/view/117666/vprwyp.htm`,
104+
],
105+
].forEach(([input, expected]) =>
106+
it(`should generate link for ${input}`, () => {
107+
expect(helionReflink(input)).to.eql(expected);
108+
}),
109+
);
110+
});
111+
});

src/commands/reflink.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
const X_KOM_PATTERN = /^https?:\/\/([^.]+\.)?x-kom.pl/;
2+
const X_KOM_PARTNER_ID = `100162370`;
3+
4+
const HELION_PARTNER_ID = '117666';
5+
const HELION_ID_PATTERN = /^https?:\/\/([^.]+).*,(.*?)\.htm/;
6+
const HELION_DOMAINS = [
7+
`helion`,
8+
`onepress`,
9+
`septem`,
10+
`sensus`,
11+
`dlabystrzakow`,
12+
`bezdroza`,
13+
`ebookpoint`,
14+
`videopoint`,
15+
];
16+
17+
export const isXKomReflink = (url: string) => X_KOM_PATTERN.test(url);
18+
19+
export const xKomReflink = (url: string) => {
20+
if (!isXKomReflink(url)) {
21+
return null;
22+
}
23+
24+
const suffix = `?partnerid=${X_KOM_PARTNER_ID}&sm12=NDY=&ts=1641758054&token=6ab7b9cde43c838f9e76042a3b8bfdcd`;
25+
const mainLink = url.split('#')[0];
26+
return mainLink + suffix + '&' + mainLink.length;
27+
};
28+
29+
export const isHelionReflink = (url: string) => {
30+
const maybeMatch = url.match(HELION_ID_PATTERN);
31+
if (!maybeMatch) {
32+
return false;
33+
}
34+
35+
const [_, domain, productId] = maybeMatch;
36+
37+
if (!HELION_DOMAINS.includes(domain) || !productId) {
38+
return false;
39+
}
40+
41+
return true;
42+
};
43+
44+
export const helionReflink = (url: string) => {
45+
if (!isHelionReflink(url)) {
46+
return null;
47+
}
48+
49+
const [_, domain, productId] = url.match(HELION_ID_PATTERN)!;
50+
51+
return `https://${domain}.pl/view/${HELION_PARTNER_ID}/${productId}.htm`;
52+
};
53+
54+
export const myDevilReflink = () => {
55+
return `https://www.mydevil.net/pp/9UVOSJRZIV`;
56+
};
57+
58+
export const messageToReflinks = (message: string): string[] => {
59+
const maybeLinks = message.match(/https?:\/\/[^\s]+/g);
60+
if (!maybeLinks) {
61+
return [];
62+
}
63+
64+
return maybeLinks
65+
.map((maybeLink) => {
66+
if (isXKomReflink(maybeLink)) {
67+
return xKomReflink(maybeLink);
68+
}
69+
if (isHelionReflink(maybeLink)) {
70+
return helionReflink(maybeLink);
71+
}
72+
return null;
73+
})
74+
.filter((x): x is Exclude<typeof x, null | undefined | '' | 0 | false> => !!x);
75+
};

0 commit comments

Comments
 (0)