Skip to content

Commit

Permalink
Some things
Browse files Browse the repository at this point in the history
  • Loading branch information
KrisXV committed Oct 21, 2020
1 parent 4dba420 commit 129e491
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 25 deletions.
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ server/chat-plugins/random-battles.ts @KrisXV @TheImmortal
server/chat-plugins/repeats.ts @AnnikaCodes
server/chat-plugins/rock-paper-scissors.ts @mia-pi-git
server/chat-plugins/scavenger*.ts @xfix @sparkychildcharlie
server/chat-plugins/the-studio.ts @KrisXV
server/chat-plugins/trivia.ts @AnnikaCodes
4 changes: 2 additions & 2 deletions server/chat-commands/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2564,8 +2564,8 @@ export const commands: ChatCommands = {
const [link, comment] = Utils.splitFirst(target, ',');

let buf;
if (YoutubeInterface.linkRegex.test(link)) {
const YouTube = new YoutubeInterface();
const YouTube = new YoutubeInterface();
if (YouTube.linkRegex.test(link)) {
buf = await YouTube.generateVideoDisplay(link);
} else {
try {
Expand Down
67 changes: 45 additions & 22 deletions server/chat-plugins/the-studio.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
/**
* The Studio room chat-plugin.
* Supports scrobbling and searching for music from last.fm.
* Also supports storing and suggesting recommendations.
* Written by Kris, loosely based on the concept from bumbadadabum.
* @author Kris
*/

import {FS} from '../../lib/fs';
import {Net} from '../../lib/net';
import {Utils} from '../../lib/utils';
import {YoutubeInterface} from './youtube';

const YouTube = new YoutubeInterface();
import {YouTube} from './youtube';

const LASTFM_DB = 'config/chat-plugins/lastfm.json';
const RECOMMENDATIONS = 'config/chat-plugins/the-studio.json';
Expand Down Expand Up @@ -178,7 +184,7 @@ class RecommendationsInterface {
}

checkRoom(room: Room | null) {
if (!room || room.roomid !== 'thestudio') {
if (room?.roomid !== 'thestudio') {
throw new Chat.ErrorMessage(`This command can only be used in The Studio.`);
}
}
Expand All @@ -193,9 +199,11 @@ class RecommendationsInterface {
throw new Chat.ErrorMessage(`The song titled '${title}' by ${artist} is already recommended.`);
}
if (!/^https?:\/\//.test(url)) url = `https://${url}`;
if (!YoutubeInterface.linkRegex.test(url)) {
if (!YouTube.linkRegex.test(url)) {
throw new Chat.ErrorMessage(`Please provide a valid YouTube link.`);
}
url = url.split('&')[0];
this.checkTags(tags);
// JUST in case
if (!recommendations.saved) recommendations.saved = [];
const rec: Recommendation = {artist, title, url, description, tags, userData: {name: username}, likes: 0};
Expand Down Expand Up @@ -227,13 +235,15 @@ class RecommendationsInterface {
if (this.get(artist, title)) {
throw new Chat.ErrorMessage(`The song titled '${title}' by ${artist} is already recommended.`);
}
if (recommendations.suggested.find(x => toID(x.title) === toID(title) && toID(x.artist) === toID(artist))) {
if (this.get(artist, title, null, true)) {
throw new Chat.ErrorMessage(`The song titled '${title}' by ${artist} is already suggested.`);
}
if (!/^https?:\/\//.test(url)) url = `https://${url}`;
if (!YoutubeInterface.linkRegex.test(url)) {
if (!YouTube.linkRegex.test(url)) {
throw new Chat.ErrorMessage(`Please provide a valid YouTube link.`);
}
url = url.split('&')[0];
this.checkTags(tags);
const rec: Recommendation = {artist, title, url, description, tags, userData: {name: username}, likes: 0};
if (avatar) rec.userData.avatar = avatar;
recommendations.suggested.push(rec);
Expand Down Expand Up @@ -326,21 +336,34 @@ class RecommendationsInterface {
saveRecommendations();
}

get(artist: string, title: string, submitter?: string, fromSuggestions = false) {
get(artist: string, title: string, submitter: string | null = null, fromSuggestions = false) {
let recs = recommendations.saved;
if (fromSuggestions) recs = recommendations.suggested;
return recs.find(x => toID(x.artist) === toID(artist) &&
return recs.find(x => (
toID(x.artist) === toID(artist) &&
toID(x.title) === toID(title) &&
(submitter ? toID(x.userData.name) === toID(submitter) : true));
(!submitter || toID(x.userData.name) === toID(submitter))
));
}

getIndex(artist: string, title: string, submitter?: string, fromSuggestions = false) {
getIndex(artist: string, title: string, submitter: string | null = null, fromSuggestions = false) {
let recs = recommendations.saved;
if (fromSuggestions) recs = recommendations.suggested;
const index = recs.findIndex(x => toID(x.artist) === toID(artist) &&
toID(x.title) === toID(title) &&
(submitter ? toID(x.userData.name) === toID(submitter) : true));
return index;
return recs.findIndex(x => (
toID(x.artist) === toID(artist) &&
toID(x.title) === toID(title) &&
(!submitter || toID(x.userData.name) === toID(submitter))
));
}

checkTags(tags: string[]) {
const cleansedTags = new Set<ID>();
for (const tag of tags) {
if (cleansedTags.has(toID(tag))) {
throw new Chat.ErrorMessage(`Duplicate tag: ${tag.trim()}`);
}
cleansedTags.add(toID(tag));
}
}
}

Expand Down Expand Up @@ -447,10 +470,12 @@ export const commands: ChatCommands = {
const cleansedTags = tags.map(x => x.trim());
Recs.suggest(artist, title, url, description, user.name, cleansedTags, String(user.avatar));
this.sendReply(`Your suggestion for '${title}' by ${artist} has been submitted.`);
room.sendRankedUsers(
`|html|${await Recs.render({artist, title, url, description, userData: {name: user.name, avatar: String(user.avatar)}, tags: cleansedTags, likes: 0}, true)}`,
'%'
);
const html = await Recs.render({
artist, title, url, description,
userData: {name: user.name, avatar: String(user.avatar)},
tags: cleansedTags, likes: 0,
}, true);
room.sendRankedUsers(`|html|${html}`, '%');
},
suggestrecommendationhelp: [
`/suggestrecommendation artist | song title | url | description | tag1 | tag2 | ... - Suggest a song recommendation.`,
Expand Down Expand Up @@ -569,9 +594,7 @@ export const commands: ChatCommands = {
export const pages: PageTable = {
async recommendations(query, user, connection) {
const room = this.requireRoom();
if (!room.checkModjoin(user)) {
throw new Chat.ErrorMessage(`Access denied.`);
}
this.checkCan('mute', null, room);
if (!user.inRooms.has(room.roomid)) throw new Chat.ErrorMessage(`You must be in ${room.title} to view this page.`);
this.title = 'Recommendations';
let buf = `<div class="pad">`;
Expand Down
2 changes: 1 addition & 1 deletion server/chat-plugins/youtube.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class YoutubeInterface {
interval: NodeJS.Timer | null;
intervalTime: number;
data: ChannelData;
static linkRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)(\/|$)/i;
linkRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)(\/|$)/i;
constructor(data?: ChannelData) {
this.data = data ? data : {categories: [], channels: {}};
this.interval = null;
Expand Down
1 change: 1 addition & 0 deletions server/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ export class CommandContext extends MessageContext {
return false;
}
if (err.name.endsWith('Interruption')) {
this.update();
return;
}
Monitor.crashlog(err, 'An async chat command', {
Expand Down

0 comments on commit 129e491

Please sign in to comment.