Typescript continues

This commit is contained in:
Christer Warén 2023-06-07 06:41:58 +03:00
parent 25ac99379b
commit 16ef8e70e6
10 changed files with 129 additions and 142 deletions

View File

@ -1,34 +1,21 @@
import { Guild } from 'discord.js';
import fs, { NoParamCallback } from 'fs';
import fs from 'fs';
import path from 'path';
import { state } from './Radio';
import { statistics } from './Statistics';
interface entry {
export interface datastore {
guild: {
id: string,
name?: string
},
statistics: {
[key: string]: {
"time": number,
"used": number
}
} | {},
state: {
channels: {
"text": string,
"voice": string
},
date: string,
station: {
name: string,
owner: string
}
} | {},
statistics: statistics | {},
state: state | {},
updated?: string
}
export default class {
map: Map<string, any>;
export default class Datastore {
map: Map<string, datastore>;
constructor() {
this.map = new Map();
this.loadData();
@ -66,7 +53,7 @@ export default class {
}
createEntry(id: string){
let newData: entry = {
let newData: datastore = {
guild: {
id: id,
},
@ -89,7 +76,7 @@ export default class {
return this.map.get(id);
}
updateEntry(guild: Guild | { id: string, name: string }, newData: entry) {
updateEntry(guild: Guild | { id: string, name: string }, newData: datastore) {
newData.guild.name = guild.name;
let date = new Date();
@ -100,32 +87,12 @@ export default class {
//this.showEntry(this.getEntry(guild.id));
}
showEntry(data : entry){
showEntry(data : datastore){
console.log(data);
}
createTestFile () {
let newData = {
"guild": {
"id": "test",
"name": "Test"
},
"statistics": {
"test": {
"time": 0,
"used": 0
}
},
"state": {
}
}
this.updateEntry(newData.guild, newData);
}
saveEntry(file: string, data: entry) {
fs.writeFile(path.join(path.dirname(__dirname), '../../datastore') + "/" + file + ".json", JSON.stringify(data, null, 4), 'utf8', function(err: any) {
saveEntry(file: string, data: datastore) {
fs.writeFile(path.join(path.dirname(__dirname), '../../datastore') + "/" + file + ".json", JSON.stringify(data, null, 4), 'utf8', function(err: NodeJS.ErrnoException | null) {
if (err) {
}

View File

@ -1,27 +1,40 @@
import { Guild, GuildMember, TextBasedChannel, VoiceBasedChannel, VoiceChannel } from "discord.js";
import { Channel, Collection, GuildMember, OAuth2Guild, TextBasedChannel, VoiceBasedChannel, VoiceChannel } from "discord.js";
import { getVoiceConnection, joinVoiceChannel, VoiceConnection } from "@discordjs/voice";
import RadioClient from "../../Client";
import { station } from "./Stations";
import { datastore } from "./Datastore";
export interface radio {
textChannel: TextBasedChannel | null,
voiceChannel: VoiceBasedChannel,
textChannel: Channel | TextBasedChannel | undefined | null,
voiceChannel: Channel | VoiceBasedChannel | undefined,
connection: VoiceConnection | null,
message: null,
station: station,
datastore?: any,
datastore?: datastore,
currentTime?: number,
startTime: number,
playTime?: number,
}
export interface state extends Object {
channels: {
"text": string,
"voice": string
},
date: string,
station: {
name: string,
owner: string
}
}
export default class Radio extends Map {
constructor() {
super();
}
save(client: RadioClient) {
save(client: RadioClient): void {
let currentRadios = this.keys();
let radio = currentRadios.next();
@ -29,7 +42,7 @@ export default class Radio extends Map {
let currentRadio = this.get(radio.value);
if (currentRadio) {
currentRadio.guild = client.datastore?.getEntry(radio.value).guild;
currentRadio.guild = client.datastore?.getEntry(radio.value)?.guild;
client.statistics?.update(client, currentRadio.guild, currentRadio);
client.funcs.saveState(client, currentRadio.guild, currentRadio);
@ -42,29 +55,32 @@ export default class Radio extends Map {
}
}
restore(client: RadioClient, guilds: any) {
restore(client: RadioClient, guilds: Collection<string, OAuth2Guild>): void {
if(!client.stations) return;
guilds.forEach(async (guild: Guild) => {
guilds.forEach(async (guild: OAuth2Guild) => {
let state = client.funcs.loadState(client, guild);
if(!state) return;
if(!state.station || !state.channels.voice || !state.channels.text) return;
if(!state.hasOwnProperty('station') || !state.hasOwnProperty('channels')) return;
let voiceChannel = client.channels.cache.get(state.channels.voice);
if(!voiceChannel || !(voiceChannel instanceof VoiceChannel)) return;
if(voiceChannel.members.filter((member: GuildMember) => !member.user.bot).size === 0) return;
const sstation = await client.stations?.search(state.station.name, "direct");
const sstation = client.stations?.search(state.station.name, "direct");
let station = sstation;
if(!station) return;
const construct: any = {
let date = new Date();
const construct: radio = {
textChannel: client.channels.cache.get(state.channels.text),
voiceChannel: client.channels.cache.get(state.channels.voice),
connection: null,
message: null,
station: station
station: station,
startTime: date.getTime()
};
this.set(guild.id, construct);
@ -81,6 +97,7 @@ export default class Radio extends Map {
let date = new Date();
construct.startTime = date.getTime();
client.datastore?.checkEntry(guild.id);
//@ts-ignore
client.funcs.play(client, null, guild, station);
} catch (error) {
console.log(error);

View File

@ -1,62 +1,44 @@
const _importDynamic = new Function('modulePath', 'return import(modulePath)');
// @ts-ignore
const fetch = (...args: any) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args));
import logger from "../funcs/logger";
export interface station {
name: string,
owner: string,
logo: string,
stream: any
stream: {
[key: string]: string
}
}
export default class Stations extends Array {
logger: any;
counter: number;
constructor() {
super();
this.counter = 0;
}
async fetch(options: any){
async fetch(options: { url: string, show?: boolean }){
try {
logger('Stations', 'Started fetching list - ' + options.url);
let list = await fetch(options.url)
let stations = await fetch(options.url)
.then(this.checkFetchStatus)
.then((response: { json: () => station; }) => response.json());
.then((response: { json: () => station[]; }) => response.json());
if(list){
this.length = 0;
list.forEach((station: station) => {
try {
this.push(station);
} catch (error) {
}
});
if(options.show){
list.forEach((station: { name: any; }) => {
logger('Stations', station.name);
});
if(!stations) return;
for (const station of stations){
this.push(station.name);
if(options.show) logger('Stations', station.name);
}
list.forEach(async (station: station) => {
try {
let stationTest = await fetch(station.stream[station.stream.default]);
if(stationTest.ok === true) return;
this.splice(this.indexOf(station),1);
} catch (error) {
this.splice(this.indexOf(station),1);
}
});
}
this.counter = 0;
logger('Stations', 'Successfully fetched list');
} catch (error) {
logger('Stations', 'Fetching list failed');
console.error(error + "\n");
if(this.length == 0) this.fetch(options);
this.counter = this.counter + 1;
if(this.length == 0 && 5 < this.counter) this.fetch(options);
}
}
@ -126,21 +108,23 @@ export default class Stations extends Array {
}
}
}
let highestProbabilityStation : any | { station: string, name: string, probability: number } | string | null = null;
/*let highestProbabilityStation : { station: string, name: string, probability: number } | string | undefined;
for (let i = 0; i < foundStations.length; i++) {
if (
!highestProbabilityStation ||
//@ts-ignore
highestProbabilityStation.probability < foundStations[i].probability
)
highestProbabilityStation = foundStations[i];
if (
highestProbabilityStation &&
//@ts-ignore
highestProbabilityStation.probability === foundStations[i].probability
) {
highestProbabilityStation = foundStations[i].station;
}
}
return highestProbabilityStation;
return highestProbabilityStation;*/
}
}
};

View File

@ -2,8 +2,17 @@ import { Guild } from "discord.js";
import RadioClient from "../../Client";
import { radio } from "./Radio";
export interface statistics {
[key: string]: statistic
}
interface statistic {
"time": number,
"used": number
}
export default class Statistics {
map: Map<any, any>;
map: Map<string, statistics>;
constructor() {
this.map = new Map();
@ -16,19 +25,26 @@ export default class Statistics {
radio.datastore = client.datastore?.getEntry(guild.id);
//@ts-ignore
if(!radio.datastore.statistics[radio.station.name]){
radio.datastore.statistics[radio.station.name] = {};
radio.datastore.statistics[radio.station.name].time = 0;
radio.datastore.statistics[radio.station.name].used = 0;
//@ts-ignore
radio.datastore.statistics[radio.station.name] = {
time: 0,
used: 0
};
//@ts-ignore
client.datastore?.updateEntry(guild, radio.datastore);
}
let date = new Date();
radio.currentTime = date.getTime();
radio.playTime = radio.currentTime - radio.startTime;
//@ts-ignore
radio.datastore.statistics[radio.station.name].time = parseInt(radio.datastore.statistics[radio.station.name].time) + radio.playTime;
//@ts-ignore
radio.datastore.statistics[radio.station.name].used = parseInt(radio.datastore.statistics[radio.station.name].used)+1;
//@ts-ignore
client.datastore?.updateEntry(guild, radio.datastore);
this.calculateGlobal(client);
}
@ -39,7 +55,7 @@ export default class Statistics {
let guilds = client.datastore.map.keys();
let stations = client.stations;
let statistics : any = {};
let statistics : statistics = {};
if(!client.stations) return;
@ -50,14 +66,18 @@ export default class Statistics {
if(calculation.value != 'global'){
if(stations){
for(const station of stations) {
if(currentGuild.statistics[station.name] && currentGuild.statistics[station.name].time && parseInt(currentGuild.statistics[station.name].time) != 0 && currentGuild.statistics[station.name].used && parseInt(currentGuild.statistics[station.name].used) != 0){
//@ts-ignore
if(currentGuild.statistics[station.name] && currentGuild.statistics[station.name]?.time && parseInt(currentGuild.statistics[station.name].time) != 0 && currentGuild.statistics[station.name].used && parseInt(currentGuild.statistics[station.name].used) != 0){
if(!statistics[station.name]){
statistics[station.name] = {};
statistics[station.name].time = 0;
statistics[station.name].used = 0;
statistics[station.name] = {
time: 0,
used: 0
};
}
//@ts-ignore
statistics[station.name].time = parseInt(statistics[station.name].time)+parseInt(currentGuild.statistics[station.name].time);
//@ts-ignore
statistics[station.name].used = parseInt(statistics[station.name].used)+parseInt(currentGuild.statistics[station.name].used);
}
}
@ -66,11 +86,13 @@ export default class Statistics {
calculation = guilds.next();
}
let newData : any = {};
newData.guild = {};
newData.guild.id = "global";
newData.guild.name = "global";
newData.statistics = statistics;
let newData = {
guild: {
id: "global",
name: "global"
},
statistics: statistics
};
client.datastore.updateEntry(newData.guild, newData);
}

View File

@ -4,7 +4,7 @@ import RadioClient from "../../Client";
import { station } from "./Stations";
export default class Streamer {
map: any;
map: Map<string, any>;
mode: "auto" | "manual" = "manual";
constructor() {
@ -37,12 +37,11 @@ export default class Streamer {
refresh(client: RadioClient){
this.init(client);
let streamers = this.map.keys();
streamers.forEach((streamer: any) => {
for (const streamer of this.map.keys()){
if(client.stations?.findIndex((station: station) => station.name == streamer) == -1){
this.stop(streamer);
}
});
}
}
play(station: station) {
@ -94,14 +93,14 @@ export default class Streamer {
return audioPlayer;
}
stop(station: station){
let audioPlayer = this.map.get(station.name);
stop(streamer: string){
let audioPlayer = this.map.get(streamer);
if(audioPlayer){
logger('Streamer', station.name + " / " + "Stop");
logger('Streamer', streamer + " / " + "Stop");
audioPlayer.removeAllListeners();
audioPlayer.stop();
}
this.map.delete(station.name);
this.map.delete(streamer);
}
listen(station: station) {
@ -113,7 +112,7 @@ export default class Streamer {
leave(client: RadioClient) {
if(!client.stations) return;
client.stations.forEach((station: station) => {
this.stop(station);
this.stop(station.name);
});
}
};

View File

@ -1,10 +1,7 @@
import { ActionRowBuilder, AnyComponentBuilder, APIActionRowComponent, APISelectMenuOption, ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js";
import { ActionRowBuilder, APISelectMenuOption, ButtonInteraction, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js";
import RadioClient from "../../Client";
import Streamer from "../classes/Streamer";
import commands from "../commands";
const _importDynamic = new Function('modulePath', 'return import(modulePath)');
// @ts-ignore
const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args));
export default {
name: 'maintenance',

View File

@ -1,10 +1,11 @@
import RadioClient from "../../Client";
import Datastore from "../classes/Datastore";
import Datastore, { datastore } from "../classes/Datastore";
import Radio from "../classes/Radio";
import Stations from "../classes/Stations";
import Streamer from "../classes/Streamer";
import Statistics from "../classes/Statistics";
import commands from "../commands";
import { OAuth2Guild } from "discord.js";
export default async function ready(client: RadioClient) {
client.funcs.logger("Bot", "Ready");
@ -13,7 +14,7 @@ export default async function ready(client: RadioClient) {
client.funcs.logger('Datastore', 'Initialize');
client.datastore = new Datastore();
client.datastore.map.forEach((datastore: { guild: { id: string; name: string; }; }) => {
client.datastore.map.forEach((datastore: datastore) => {
client.funcs.logger('Datastore', datastore.guild.id + " / " + datastore.guild.name);
});
@ -45,7 +46,7 @@ export default async function ready(client: RadioClient) {
client.funcs.logger('Guilds', 'Started fetching list');
let guilds = await client.guilds.fetch();
guilds.forEach((guild: { id: string; name: string; }) => {
guilds.forEach((guild: OAuth2Guild) => {
client.funcs.logger('Guilds', guild.id + " / " + guild.name);
});

View File

@ -1,15 +1,12 @@
import { Guild } from "discord.js";
import { OAuth2Guild } from "discord.js";
import RadioClient from "../../Client";
export default function loadState(client: RadioClient, guild: Guild){
export default function loadState(client: RadioClient, guild: OAuth2Guild) {
if(!client.datastore) return;
let data = client.datastore.getEntry(guild.id);
if(!data) return;
let state;
state = data.state;
let state = data.state;
if(!state) return;
data.state = {};
client.datastore.updateEntry(guild, data);
return state;

View File

@ -1,8 +1,8 @@
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, Guild, StringSelectMenuInteraction } from "discord.js";
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, ColorResolvable, EmbedBuilder, Guild, OAuth2Guild, StringSelectMenuInteraction } from "discord.js";
import RadioClient from "../../Client";
import { station } from "../classes/Stations";
export default async function play(client: RadioClient, interaction: ChatInputCommandInteraction | StringSelectMenuInteraction | null, guild: Guild | null, station: station) {
export default async function play(client: RadioClient, interaction: ChatInputCommandInteraction | StringSelectMenuInteraction | null, guild: OAuth2Guild | Guild | null, station: station) {
if(!guild) return;
const radio = client.radio?.get(guild.id);

View File

@ -9,15 +9,18 @@ export default function saveState(client: RadioClient, guild: Guild, radio: radi
let date = new Date();
let data = client.datastore.getEntry(guild.id);
data.state = {};
data.state.channels = {};
data.state.channels.text = radio.textChannel?.id;
data.state.channels.voice = radio.voiceChannel.id;
data.state.date = date.toISOString();
data.state.station = {};
data.state.station.name = radio.station.name;
data.state.station.owner = radio.station.owner;
if(!data) return;
data.state = {
channels: {
text: radio.textChannel?.id,
voice: radio.voiceChannel?.id
},
date: date.toISOString(),
station: {
name: radio.station.name,
owner: radio.station.owner
}
};
client.datastore.updateEntry(guild, data);
}