diff --git a/package-lock.json b/package-lock.json index 78087f4..54f4eb0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,6 +39,7 @@ "typescript": "^4.2.4" }, "devDependencies": { + "@types/chai-string": "^1.4.2", "@types/ws": "^7.4.4" } }, @@ -256,6 +257,15 @@ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.18.tgz", "integrity": "sha512-rS27+EkB/RE1Iz3u0XtVL5q36MGDWbgYe7zWiodyKNUnthxY0rukK5V36eiUCtCisB7NN8zKYH6DO2M37qxFEQ==" }, + "node_modules/@types/chai-string": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@types/chai-string/-/chai-string-1.4.2.tgz", + "integrity": "sha512-ld/1hV5qcPRGuwlPdvRfvM3Ka/iofOk2pH4VkasK4b1JJP1LjNmWWn0LsISf6RRzyhVOvs93rb9tM09e+UuF8Q==", + "dev": true, + "dependencies": { + "@types/chai": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", @@ -3923,6 +3933,15 @@ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.18.tgz", "integrity": "sha512-rS27+EkB/RE1Iz3u0XtVL5q36MGDWbgYe7zWiodyKNUnthxY0rukK5V36eiUCtCisB7NN8zKYH6DO2M37qxFEQ==" }, + "@types/chai-string": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@types/chai-string/-/chai-string-1.4.2.tgz", + "integrity": "sha512-ld/1hV5qcPRGuwlPdvRfvM3Ka/iofOk2pH4VkasK4b1JJP1LjNmWWn0LsISf6RRzyhVOvs93rb9tM09e+UuF8Q==", + "dev": true, + "requires": { + "@types/chai": "*" + } + }, "@types/json-schema": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", diff --git a/package.json b/package.json index eebbd9b..8bed837 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "typescript": "^4.2.4" }, "devDependencies": { + "@types/chai-string": "^1.4.2", "@types/ws": "^7.4.4" } } diff --git a/src/discordParser.ts b/src/discordParser.ts index 870fbb5..030c773 100644 --- a/src/discordParser.ts +++ b/src/discordParser.ts @@ -1,7 +1,9 @@ -import { Client, TextChannel } from 'discord.js'; +import { Client, Message, TextChannel } from 'discord.js'; import dedent from 'ts-dedent'; import { ImplementableApi } from './implementableApi'; +import { once as eventsOnce } from 'events'; + namespace DiscordParser { export type Config = ImplementableApi.Config & { token: string; @@ -13,23 +15,28 @@ namespace DiscordParser { }; } -///Penser a split mes event peertube Ytb en 2 channel differents class DiscordParser extends ImplementableApi { readonly token: string; readonly keyWord: string; - readonly channels: { - readonly ChannelYtb: TextChannel; - readonly ChannelPeerTube: TextChannel; - }; + readonly channels: Promise<{ + [key: string]: TextChannel; + ChannelYtb: TextChannel; + ChannelPeerTube: TextChannel; + }>; readonly client: Client; constructor(readonly config: DiscordParser.Config) { super(config); this.token = config.token; this.keyWord = config.keyWord; - this.settingEvents(); + this.client = this.instantiateClient(); - this.channels = this.setChannel(config.channelsId); + this.channels = eventsOnce(this.client, 'ready').then(() => { + return this.setChannel(config.channelsId); + }); + this.channels.then(() => { + this.settingEvents(); + }); } private setChannel(ids: { @@ -46,12 +53,14 @@ class DiscordParser extends ImplementableApi { ChannelPeerTube?: TextChannel; } = {}; // construct and check the channels + for (const key in ids) { if (ids[key]) { + // console.log(ids[key]); const tmpChannel = this.client.channels.resolve(ids[key]); if (tmpChannel) if (tmpChannel instanceof TextChannel) - resp[key] = tmpChannel; + resp[key.slice(2)] = tmpChannel; else throw new Error('The channel must be a TextChannel'); else throw new Error( @@ -67,6 +76,10 @@ class DiscordParser extends ImplementableApi { ChannelPeerTube: resp.ChannelPeerTube, ChannelYtb: resp.ChannelYtb, }; + + console.log(resp); + // console.log(resp.ChannelYtb); + throw new Error('Theres an issue concerned the channel check'); } @@ -80,33 +93,51 @@ class DiscordParser extends ImplementableApi { switch (message.type) { case 'newEntriesNotify': this.sendMsgYtb( - `New YouTubes entries received :\n${JSON.parse( - message.rawContent - ).items.map((item: any) => `Author : ${item.author}`)}` + `New YouTubes entries received :\n${message.rawContent.items.map( + (item: any) => + `Author : ${item.author}\nTitle: ${item.title}\nlink: ${item.link}` + )}` ); default: break; } } - private sendMsgYtb(message: string) { - this.channels.ChannelYtb.send(message); + private async sendMsgYtb(message: string) { + const resolvedChannel = await this.channels; + resolvedChannel.ChannelYtb.send(message); } - private sendMsgPeerTube(message: string) { - this.channels.ChannelPeerTube.send(message); + private async sendMsgPeerTube(message: string) { + const resolvedChannel = await this.channels; + resolvedChannel.ChannelPeerTube.send(message); } private settingEvents(): void { - this.client.on('message', (message) => { - const msg_splitted = message.content.split(' '); - if (msg_splitted[0] === this.keyWord) { - // if (!this.channel) { - // this.channel = message.channel; - // } - switch (msg_splitted[1]) { - case 'add': + this.on('message', async (message: Message) => { + const resolvedChannel = await this.channels; + let id_arr: string[] = []; + for (const key in this.channels) + id_arr.push(resolvedChannel[key].id); + + if (this.channels) + if (id_arr.includes(message.channel.id)) { + const msg_splitted = message.content.split(' '); + if (msg_splitted[0] === this.keyWord) { + switch (msg_splitted[1]) { + case 'add': + const send_message: ImplementableApi.Message = { + rawContent: { + address: msg_splitted[2], + user: message.author.toString(), + date: message.createdAt.toUTCString(), + }, + type: 'newListener', + }; + message.channel.send('Ceci est un feedback'); + this.emit('addListener', send_message); + } + } } - } }); } } diff --git a/src/logWriter.ts b/src/logWriter.ts index 0a07194..ddb1627 100644 --- a/src/logWriter.ts +++ b/src/logWriter.ts @@ -12,7 +12,9 @@ namespace LogWriter { path: string; }; } - +/** + * check nodejs buffer et throttle + */ class LogWriter extends ImplementableApi { readonly path: string; @@ -31,14 +33,15 @@ class LogWriter extends ImplementableApi { private writeMsg(message: ImplementableApi.Message): void; private writeMsg(message: ImplementableApi.Message | string) { if (typeof message !== 'string') - message = `[${message.type} :: ${new Date().toLocaleString( - 'fr-FR' - )}] ${message.rawContent} ${ - message.idListener ?? `( listener_id : ${message.idListener} )` + message = `[${message.type} :: ${new Date().toISOString()}] ${ + message.rawContent + } ${ + message.idListener ?? + `( listener_id : ${message.idListener} )\n` }`; const fd = openSync(this.path, 'a'); - const str = `[${new Date().toLocaleString('fr-FR')}] ${message}`; + const str = `[${new Date().toISOString()}] ${message}\n`; appendFileSync(fd, str); closeSync(fd); } diff --git a/src/peertubeRequester.ts b/src/peertubeRequester.ts index 83c5fcc..43d7878 100644 --- a/src/peertubeRequester.ts +++ b/src/peertubeRequester.ts @@ -15,7 +15,7 @@ namespace PeerTubeRequester { type UploadInstruction = { [key: string]: string; - channelID: string; + channelId: string; targetUrl: string; }; @@ -68,7 +68,7 @@ class PeerTubeRequester extends ImplementableApi { for (const item of items) { const media_group = item['media:group']; const args: UploadInstruction = { - channelID: 'undefined', // to do binding avec les idDeChaines Skeptikom + channelId: '848', // to do binding avec les idDeChaines Skeptikom targetUrl: item.link, }; await this.apiRequest(args); diff --git a/src/router.ts b/src/router.ts index dfd6da7..ade8de3 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,43 +1,47 @@ -import { ImplementableApi } from "./implementableApi"; +import { ImplementableApi } from './implementableApi'; -import { DiscordParser } from './discordParser' -import { LogWriter } from './logWriter' -import { PeerTubeRequester } from './peertubeRequester' +import { DiscordParser } from './discordParser'; +import { LogWriter } from './logWriter'; +import { PeerTubeRequester } from './peertubeRequester'; namespace Router { export type Config = { events: { - name: string, - type: 0 | 1 + name: string; + type: 'emit' | 'received'; }[]; apis: { - apiName: string - }[] - } + apiName: string; + }[]; + }; export type GlobalConfig = { router: Config; discord: DiscordParser.Config; peertubeRequester: PeerTubeRequester.Config; logWriter: LogWriter.Config; - } + }; } class Router { - api_array: {[key: string]: ImplementableApi} = {}; + api_array: { [key: string]: ImplementableApi } = {}; readonly routes: Router.Config; constructor(readonly config: Router.GlobalConfig) { this.routes = config.router; this.api_array[config.discord.name] = new DiscordParser(config.discord); - this.api_array[config.peertubeRequester.name] = new PeerTubeRequester(config.peertubeRequester); + this.api_array[config.peertubeRequester.name] = new PeerTubeRequester( + config.peertubeRequester + ); this.api_array[config.logWriter.name] = new LogWriter(config.logWriter); } public receivedMessage(message: ImplementableApi.Message) { - this.routes.apis.forEach((api) => this.api_array[api.apiName].receivedMessage(message)) + this.routes.apis.forEach((api) => + this.api_array[api.apiName].receivedMessage(message) + ); } } -export { Router }; \ No newline at end of file +export { Router }; diff --git a/tests/discord-spec.ts b/tests/discord-spec.ts index 742c923..b00ba48 100644 --- a/tests/discord-spec.ts +++ b/tests/discord-spec.ts @@ -1,11 +1,8 @@ -import chai from 'chai'; +import chai, { expect } from 'chai'; import sinon from 'ts-sinon'; import sinonChai from 'sinon-chai'; chai.use(sinonChai); -const expect = chai.expect; - -import nock, { disableNetConnect, RequestBodyMatcher } from 'nock'; import { DiscordParser } from '../src/discordParser'; @@ -20,36 +17,61 @@ const config: DiscordParser.Config = { token: 'mySecretDiscordToken', }; -//stubed imports +//mockeded imports import { Channel, ChannelManager, Client } from 'discord.js'; -import { utils } from 'mocha'; -describe.only('test DiscordParser', function () { - let clientStub: sinon.SinonStubbedInstance, - channelManagerStub: sinon.SinonStubbedInstance; +describe.skip('test DiscordParser', function () { + let clientMockOn: sinon.SinonStub, + clientMockLogin: sinon.SinonStub, + channelStub: sinon.SinonStubbedInstance, + channelManagerMockResolve: sinon.SinonStub; + before(() => { - clientStub = sinon.createStubInstance(Client); - clientStub.login.withArgs(config.token).onFirstCall().resolves('ok'); - clientStub.login.throws('Error, bad parameter or too much call'); + clientMockOn = sinon.stub(Client.prototype, 'on'); + clientMockOn.withArgs('message', sinon.match.func).onFirstCall(); + clientMockOn.throws('Error, bad parameter or too much call'); - channelManagerStub = sinon.createStubInstance(ChannelManager); - channelManagerStub.resolve + clientMockLogin = sinon.stub(Client.prototype, 'login'); + clientMockLogin + .withArgs(config.token) + .onFirstCall() + .resolves('ok') + .returnsThis(); + clientMockLogin.throws('Error, bad parameter or too much call'); + + channelStub = sinon.createStubInstance(Channel); + + channelManagerMockResolve = sinon.stub( + ChannelManager.prototype, + 'resolve' + ); + channelManagerMockResolve .withArgs(config.channelsId.idChannelPeerTube) .onFirstCall() - .returns(new Channel(new Client())) + .returns(channelStub); + channelManagerMockResolve .withArgs(config.channelsId.idChannelYtb) .onFirstCall() - .returns(new Channel(new Client())); - channelManagerStub.resolve.throws("Error Bad id's or too much call"); + .returns(channelStub); + channelManagerMockResolve.throws("Error Bad id's or too much call"); }); after(() => { - clientStub.login.restore(); - channelManagerStub.resolve.restore(); + clientMockOn.restore(); + clientMockLogin.restore(); + channelManagerMockResolve.restore(); }); - it('it will test the DiscordParser constructor', function () { + + it('it will test the DiscordParser constructor', async function () { + //when const discordParser = new DiscordParser(config); - console.log("c'est bon signe"); + // expect + expect(discordParser.token).to.be.eql(config.token); + await discordParser.channels.then((channels) => { + expect(channels.ChannelYtb.id).to.be.eql( + config.channelsId.idChannelYtb + ); + }); }); }); diff --git a/tests/index-spec.ts b/tests/index-spec.ts index 1899fe9..e593e90 100644 --- a/tests/index-spec.ts +++ b/tests/index-spec.ts @@ -13,7 +13,6 @@ import { DiscordParser } from '../src/discordParser'; import { LogWriter } from '../src/logWriter'; import { PeerTubeRequester } from '../src/peertubeRequester'; -// const path = require("path"); const well_build_routing_file: Router.GlobalConfig = require('./rsrc/wellBuildedRoutingFile.json'); describe('testing the routing part', function () { @@ -30,9 +29,9 @@ describe('testing the routing part', function () { }; const r = new Router(edit_config); - expect(r.api_array['Discord']).to.be.instanceOf( - DiscordParser - ); + // expect(r.api_array['Discord']).to.be.instanceOf( + // DiscordParser + // ); expect(r.api_array['logWriter']).to.be.instanceOf( LogWriter ); diff --git a/tests/logWriter-spec.ts b/tests/logWriter-spec.ts new file mode 100644 index 0000000..c6beee2 --- /dev/null +++ b/tests/logWriter-spec.ts @@ -0,0 +1,43 @@ +import chai, { expect } from 'chai'; +import sinon from 'ts-sinon'; +import sinonChai from 'sinon-chai'; + +chai.use(sinonChai); + +import { withDir } from 'tmp-promise'; +import { existsSync, readFileSync } from 'fs'; + +import { LogWriter } from '../src/logWriter'; + +const config: LogWriter.Config = { + name: 'logWirterTested', + path: 'it will be set by tmp-promise', +}; + +describe('test logWriter', function () { + describe('constructor', function () { + it('will test the constructor with a new file', async function () { + await withDir( + async (dir) => { + const log_writer = new LogWriter({ + ...config, + ...{ path: dir.path + '/toto.log' }, + }); + expect(existsSync(dir.path + '/toto.log')).to.be.true; + expect( + readFileSync(dir.path + '/toto.log', { + encoding: 'utf-8', + }) + ).to.match(/LogWriter is running\n+$/g); + }, + { unsafeCleanup: true } + ); + }); + }); + + describe('received message', function () { + it('will test the print function', function () {}); + }); +}); + +//presenter le projet . listener -> import sous forme de plugin diff --git a/tests/peertubeRequeter-spec.ts b/tests/peertubeRequeter-spec.ts index 83f676b..17099a1 100644 --- a/tests/peertubeRequeter-spec.ts +++ b/tests/peertubeRequeter-spec.ts @@ -9,7 +9,6 @@ import nock, { disableNetConnect, RequestBodyMatcher } from 'nock'; import { ImplementableApi } from '../src'; import { PeerTubeRequester } from '../src/peertubeRequester'; -import { Request } from 'node-fetch'; const paramsPeerTube: PeerTubeRequester.Config = { name: 'testedRequester', @@ -42,7 +41,7 @@ const newEntriesMessage: ImplementableApi.Message = { }; const UploadInstruction = { - channelID: 'undefined', //todo uncompleted test but incompleted function too + channelId: 'undefined', //todo uncompleted test but incompleted function too targetUrl: 'myTargerUrl', }; @@ -64,6 +63,7 @@ const bodyTokenRequest: RequestBodyMatcher = { username: paramsPeerTube.username, password: paramsPeerTube.password, }; + describe('PeerTube Requester Test', function () { before(function () { disableNetConnect(); @@ -81,36 +81,34 @@ describe('PeerTube Requester Test', function () { .reply(200, expectedReplyOauthClient) .post(`/users/token`, bodyTokenRequest) .times(3) - .reply(200, expectedReplyTokenAddress) - .post(`/videos/imports`, { - channelID: 'undefined', - targeUrl: newEntriesMessage.rawContent.items[0].link, - }) + .reply(200, expectedReplyTokenAddress); + const import_scope = nock( + `https://${paramsPeerTube.domain_name}/api/v1` + ) .matchHeader( - 'Authorization', + 'authorization', `Bearer ${expectedReplyTokenAddress.access_token}` ) - .reply(200) - .post(`/videos/imports`, { - channelID: 'undefined', - targeUrl: newEntriesMessage.rawContent.items[1].link, - }) - .matchHeader( - 'Authorization', - `Bearer ${expectedReplyTokenAddress.access_token}` - ) - .reply(200) - .post(`/videos/imports`, { - channelID: 'undefined', - targeUrl: newEntriesMessage.rawContent.items[2].link, - }) - .matchHeader( - 'Authorization', - `Bearer ${expectedReplyTokenAddress.access_token}` - ) - .reply(200); + .post(`/videos/imports`, (reqBody) => { + let links: string[] = newEntriesMessage.rawContent.items.map( + (item: any) => item.link + ); - if (scope.isDone()) console.log(scope.activeMocks()); + const body = new URLSearchParams(reqBody); + if (body.get('channelId') === 'undefined') { + const targUrl = body.get('targetUrl'); + if (targUrl && links.includes(targUrl)) { + const index = links.findIndex( + (elmt) => elmt === targUrl + ); + links.splice(index, 1); + return true; + } + } + return false; + }) + .times(3) + .reply(200); const requester = new PeerTubeRequester(paramsPeerTube); @@ -118,6 +116,8 @@ describe('PeerTube Requester Test', function () { await requester.receivedMessage(newEntriesMessage); //expected - if (scope.isDone()) console.log(scope.activeMocks()); + // all the scope need to be completed + expect(scope.isDone()).to.be.true; + expect(import_scope.isDone()).to.be.true; }); });