Writted peertube and discordParser class, and added many test.

This commit is contained in:
Amaury
2021-05-30 15:36:20 +02:00
parent 866578f422
commit 8b3e2535e2
7 changed files with 531 additions and 103 deletions

View File

@ -1,44 +1,113 @@
import { Channel, Client } from 'discord.js';
import { isBooleanObject } from 'util/types';
import { Client, TextChannel } from 'discord.js';
import dedent from 'ts-dedent';
import { ImplementableApi } from './implementableApi';
namespace DiscordParser {
export type Config = ImplementableApi.Config & {
token: string;
channelsId: {
idChannelYtb: string;
idChannelPeerTube: string;
};
keyWord: string;
};
}
///Penser a split mes event peertube Ytb en 2 channel differents
class DiscordParser extends ImplementableApi {
readonly token: string;
readonly channelid: string;
client: Client;
readonly keyWord: string;
readonly channels: {
readonly ChannelYtb: TextChannel;
readonly ChannelPeerTube: TextChannel;
};
readonly client: Client;
constructor(readonly config: DiscordParser.Config) {
super(config);
this.token = config.token;
// this.settingEvents();
this.client = new Client();
this.instantiateClient();
this.keyWord = config.keyWord;
this.settingEvents();
this.client = this.instantiateClient();
this.channels = this.setChannel(config.channelsId);
}
private instantiateClient() {
this.client.login(this.token);
private setChannel(ids: {
[key: string]: string;
idChannelYtb: string;
idChannelPeerTube: string;
}): {
ChannelYtb: TextChannel;
ChannelPeerTube: TextChannel;
} {
let resp: {
[key: string]: TextChannel | undefined;
ChannelYtb?: TextChannel;
ChannelPeerTube?: TextChannel;
} = {};
// construct and check the channels
for (const key in ids) {
if (ids[key]) {
const tmpChannel = this.client.channels.resolve(ids[key]);
if (tmpChannel)
if (tmpChannel instanceof TextChannel)
resp[key] = tmpChannel;
else throw new Error('The channel must be a TextChannel');
else
throw new Error(
dedent`The channel cannot be found by the bot.
Check if you had the bot to your server or if the channel ID is correct`
);
}
}
// return the well formed object
if (resp.ChannelPeerTube)
if (resp.ChannelYtb)
return {
ChannelPeerTube: resp.ChannelPeerTube,
ChannelYtb: resp.ChannelYtb,
};
throw new Error('Theres an issue concerned the channel check');
}
private instantiateClient(): Client {
const newClient = new Client();
newClient.login(this.token);
return newClient;
}
public receivedMessage(message: ImplementableApi.Message) {
switch (message.type) {
case 'newEntriesNotify':
this.sendMsgYtb(
`New YouTubes entries received :\n${JSON.parse(
message.rawContent
).items.map((item: any) => `Author : ${item.author}`)}`
);
default:
break;
}
}
private sendMsg(message: string) {
// this.client.channels.resolveID();
private sendMsgYtb(message: string) {
this.channels.ChannelYtb.send(message);
}
private sendMsgPeerTube(message: string) {
this.channels.ChannelPeerTube.send(message);
}
private settingEvents(): void {
throw 'empty';
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':
}
}
});
}
}

View File

@ -1,4 +1,9 @@
import { ImplementableApi } from './implementableApi';
// Api request lib
import fetch, { FetchError, Headers } from 'node-fetch';
import { URLSearchParams } from 'url';
import FormData from 'form-data';
import dedent from 'ts-dedent';
namespace PeerTubeRequester {
export type Config = ImplementableApi.Config & {
@ -12,10 +17,6 @@ type UploadInstruction = {
[key: string]: string;
channelID: string;
targetUrl: string;
name: string;
description: string;
originallyPublishedAt: string;
thumbnailsfile: string;
};
type ClientToken = {
@ -46,71 +47,110 @@ class PeerTubeRequester extends ImplementableApi {
this.password = config.password;
}
public receivedMessage(message: ImplementableApi.Message) {
public async receivedMessage(
message: ImplementableApi.Message
): Promise<void> {
switch (message.type) {
case 'newEntriesNotify':
this.newEntriesNotify(message);
await this.newEntriesNotify(message);
break;
default:
break;
}
}
private newEntriesNotify(message: ImplementableApi.Message) {
private async newEntriesNotify(
message: ImplementableApi.Message
): Promise<void> {
// parse content
const items = message.rawContent['items'];
if (Array.isArray(items))
items.forEach((item) => {
for (const item of items) {
const media_group = item['media:group'];
const args: UploadInstruction = {
channelID: 'undefined', // to do binding avec les idDeChaines Skeptikom
description: media_group['media:description'][0],
name: media_group['media:title'][0],
originallyPublishedAt: item.pubDate,
targetUrl: media_group['media:content'][0]['$']['url'],
thumbnailsfile:
media_group['media:thumbnail'][0]['$']['url'],
targetUrl: item.link,
};
this.apiRequest(args);
});
await this.apiRequest(args);
}
}
private async apiRequest(message: UploadInstruction) {
// Auth
const client_info: ClientToken = {
...(await (
await fetch(
`https://${this.domain_name}/api/v1/oauth-clients/local`
)
).json()),
...{
grant_type: 'password',
response_type: 'code',
username: this.username,
password: this.password,
},
private async apiRequest(message: UploadInstruction): Promise<void> {
let response = await fetch(
`https://${this.domain_name}/api/v1/oauth-clients/local`
);
if (!response.ok) {
throw new Error(response.statusText); // CRASH
}
const { client_id, client_secret } = await response.json();
const client_info: { [key: string]: string } = {
client_id,
client_secret,
grant_type: 'password',
response_type: 'code',
username: this.username,
password: this.password,
};
const myAuthForm = new FormData();
for (const key in client_info) myAuthForm.append(key, message[key]);
let myParams = new URLSearchParams();
for (const key in client_info) myParams.append(key, client_info[key]);
const tokens_info: UserToken = await (
await fetch(`https://${this.domain_name}/api/v1/users/token`, {
method: 'get',
body: myAuthForm,
})
).json();
response = await fetch(
`https://${this.domain_name}/api/v1/users/token`,
{
method: 'post',
body: myParams,
}
);
if (!response.ok) {
throw new Error(response.statusText); // CRASH
}
const { access_token } = await response.json();
// Upload
const myUploadForm = new FormData();
const myUploadForm = new URLSearchParams();
const myHeader = new Headers();
myHeader.append('Authorization', `Bearer ${tokens_info.access_token}`);
myHeader.append('Authorization', `Bearer ${access_token}`);
for (const key in message) myUploadForm.append(key, message[key]);
await fetch(`https://${this.domain_name}/api/v1/videos/imports`, {
method: 'post',
headers: myHeader,
body: myUploadForm,
});
response = await fetch(
`https://${this.domain_name}/api/v1/videos/imports`,
{
method: 'post',
headers: myHeader,
body: myUploadForm,
}
);
if (!response.ok) {
switch (response.status) {
case 400:
throw new Error(
dedent`Your target URL was not accepted by the API.\
Actualy it's : ${message.targetUrl}
${response.statusText}`
);
break;
case 403:
throw new Error(response.statusText);
break;
case 409:
throw new Error(
dedent`Oops, your instance had not allowed the HTTPS import.\
Contact your administrator.
${response.statusText}`
);
break;
default:
throw new Error(
dedent`Oh, you resolved an undocumented issues.\
Please report this on the git if you have the time.
ERROR: ${response.statusText}`
);
break;
}
}
}
}