Skip to content

Commit

Permalink
feat: random radio
Browse files Browse the repository at this point in the history
  • Loading branch information
tomassasovsky committed Oct 1, 2023
1 parent 44dbc3c commit 83c26e0
Show file tree
Hide file tree
Showing 5 changed files with 228 additions and 2 deletions.
108 changes: 106 additions & 2 deletions lib/i18n/strings.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 2
/// Strings: 184 (92 per locale)
/// Strings: 196 (98 per locale)
///
/// Built on 2023-10-01 at 22:09 UTC
/// Built on 2023-10-01 at 23:21 UTC
// coverage:ignore-file
// ignore_for_file: type=lint
Expand Down Expand Up @@ -427,6 +427,8 @@ class StringsCommandsRadioChildrenEn {
StringsCommandsRadioChildrenRecognizeEn._(_root);
late final StringsCommandsRadioChildrenUpvoteEn upvote =
StringsCommandsRadioChildrenUpvoteEn._(_root);
late final StringsCommandsRadioChildrenPlayRandomEn playRandom =
StringsCommandsRadioChildrenPlayRandomEn._(_root);
}

// Path: services.music.trackStuck
Expand Down Expand Up @@ -546,6 +548,24 @@ class StringsCommandsRadioChildrenUpvoteEn {
StringsCommandsRadioChildrenUpvoteErrorsEn._(_root);
}

// Path: commands.radio.children.playRandom
class StringsCommandsRadioChildrenPlayRandomEn {
StringsCommandsRadioChildrenPlayRandomEn._(this._root);

final StringsEn _root; // ignore: unused_field

// Translations
String get command => 'play-random';
String get description => 'Plays a random radio station';
String get searching => 'Searching for a random radio station...';
String get startedPlaying => 'Started playing';
String startedPlayingDescription(
{required Object radio, required Object mention}) =>
'Radio ${radio} started playing.\n\nRequested by ${mention}';
late final StringsCommandsRadioChildrenPlayRandomErrorsEn errors =
StringsCommandsRadioChildrenPlayRandomErrorsEn._(_root);
}

// Path: commands.radio.children.recognize.errors
class StringsCommandsRadioChildrenRecognizeErrorsEn {
StringsCommandsRadioChildrenRecognizeErrorsEn._(this._root);
Expand All @@ -570,6 +590,17 @@ class StringsCommandsRadioChildrenUpvoteErrorsEn {
String get noRadioPlaying => 'Couldn\'t find a radio playing!';
}

// Path: commands.radio.children.playRandom.errors
class StringsCommandsRadioChildrenPlayRandomErrorsEn {
StringsCommandsRadioChildrenPlayRandomErrorsEn._(this._root);

final StringsEn _root; // ignore: unused_field

// Translations
String get noResults =>
'Couldn\'t find a random radio station :( Try again later!';
}

// Path: <root>
class StringsEs extends StringsEn {
/// You can call this constructor and build your own translation instance of this locale.
Expand Down Expand Up @@ -1043,6 +1074,9 @@ class StringsCommandsRadioChildrenEs extends StringsCommandsRadioChildrenEn {
@override
late final StringsCommandsRadioChildrenUpvoteEs upvote =
StringsCommandsRadioChildrenUpvoteEs._(_root);
@override
late final StringsCommandsRadioChildrenPlayRandomEs playRandom =
StringsCommandsRadioChildrenPlayRandomEs._(_root);
}

// Path: services.music.trackStuck
Expand Down Expand Up @@ -1226,6 +1260,34 @@ class StringsCommandsRadioChildrenUpvoteEs
StringsCommandsRadioChildrenUpvoteErrorsEs._(_root);
}

// Path: commands.radio.children.playRandom
class StringsCommandsRadioChildrenPlayRandomEs
extends StringsCommandsRadioChildrenPlayRandomEn {
StringsCommandsRadioChildrenPlayRandomEs._(StringsEs root)
: this._root = root,
super._(root);

@override
final StringsEs _root; // ignore: unused_field

// Translations
@override
String get command => 'play-random';
@override
String get description => 'Reproduce una radio aleatoria';
@override
String get searching => 'Buscando una radio aleatoria...';
@override
String get startedPlaying => 'Se ha comenzado a reproducir';
@override
String startedPlayingDescription(
{required Object radio, required Object mention}) =>
'La radio ${radio} ha comenzado a reproducirse.\n\nPedido por ${mention}';
@override
late final StringsCommandsRadioChildrenPlayRandomErrorsEs errors =
StringsCommandsRadioChildrenPlayRandomErrorsEs._(_root);
}

// Path: commands.radio.children.recognize.errors
class StringsCommandsRadioChildrenRecognizeErrorsEs
extends StringsCommandsRadioChildrenRecognizeErrorsEn {
Expand Down Expand Up @@ -1264,6 +1326,22 @@ class StringsCommandsRadioChildrenUpvoteErrorsEs
String get noRadioPlaying => 'No se está reproduciendo ninguna radio';
}

// Path: commands.radio.children.playRandom.errors
class StringsCommandsRadioChildrenPlayRandomErrorsEs
extends StringsCommandsRadioChildrenPlayRandomErrorsEn {
StringsCommandsRadioChildrenPlayRandomErrorsEs._(StringsEs root)
: this._root = root,
super._(root);

@override
final StringsEs _root; // ignore: unused_field

// Translations
@override
String get noResults =>
'No se ha podido encontrar una radio aleatoria :( Inténtalo de nuevo más tarde!';
}

/// Flat map(s) containing all translations.
/// Only for edge cases! For simple maps, use the map function of this library.
Expand Down Expand Up @@ -1420,6 +1498,19 @@ extension on StringsEn {
'You have successfully voted for the radio ${radio}! Thank you for your support :D';
case 'commands.radio.children.upvote.errors.noRadioPlaying':
return 'Couldn\'t find a radio playing!';
case 'commands.radio.children.playRandom.command':
return 'play-random';
case 'commands.radio.children.playRandom.description':
return 'Plays a random radio station';
case 'commands.radio.children.playRandom.searching':
return 'Searching for a random radio station...';
case 'commands.radio.children.playRandom.startedPlaying':
return 'Started playing';
case 'commands.radio.children.playRandom.startedPlayingDescription':
return ({required Object radio, required Object mention}) =>
'Radio ${radio} started playing.\n\nRequested by ${mention}';
case 'commands.radio.children.playRandom.errors.noResults':
return 'Couldn\'t find a random radio station :( Try again later!';
case 'services.music.trackStuck.title':
return 'Track stuck';
case 'services.music.trackStuck.description':
Expand Down Expand Up @@ -1634,6 +1725,19 @@ extension on StringsEs {
'Has votado positivamente por la radio ${radio}! Gracias por tu apoyo :D';
case 'commands.radio.children.upvote.errors.noRadioPlaying':
return 'No se está reproduciendo ninguna radio';
case 'commands.radio.children.playRandom.command':
return 'play-random';
case 'commands.radio.children.playRandom.description':
return 'Reproduce una radio aleatoria';
case 'commands.radio.children.playRandom.searching':
return 'Buscando una radio aleatoria...';
case 'commands.radio.children.playRandom.startedPlaying':
return 'Se ha comenzado a reproducir';
case 'commands.radio.children.playRandom.startedPlayingDescription':
return ({required Object radio, required Object mention}) =>
'La radio ${radio} ha comenzado a reproducirse.\n\nPedido por ${mention}';
case 'commands.radio.children.playRandom.errors.noResults':
return 'No se ha podido encontrar una radio aleatoria :( Inténtalo de nuevo más tarde!';
case 'services.music.trackStuck.title':
return 'La canción se ha quedado atascada';
case 'services.music.trackStuck.description':
Expand Down
10 changes: 10 additions & 0 deletions lib/i18n/strings.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@
"errors": {
"noRadioPlaying": "Couldn't find a radio playing!"
}
},
"playRandom": {
"command": "play-random",
"description": "Plays a random radio station",
"searching": "Searching for a random radio station...",
"startedPlaying": "Started playing",
"startedPlayingDescription": "Radio $radio started playing.\n\nRequested by $mention",
"errors": {
"noResults": "Couldn't find a random radio station :( Try again later!"
}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions lib/i18n/strings_es.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@
"errors": {
"noRadioPlaying": "No se está reproduciendo ninguna radio"
}
},
"playRandom": {
"command": "play-random",
"description": "Reproduce una radio aleatoria",
"searching": "Buscando una radio aleatoria...",
"startedPlaying": "Se ha comenzado a reproducir",
"startedPlayingDescription": "La radio $radio ha comenzado a reproducirse.\n\nPedido por $mention",
"errors": {
"noResults": "No se ha podido encontrar una radio aleatoria :( Inténtalo de nuevo más tarde!"
}
}
}
}
Expand Down
90 changes: 90 additions & 0 deletions lib/src/commands/radio.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'package:nyxx_pagination/nyxx_pagination.dart';
import 'package:radio_browser_api/radio_browser_api.dart';
import 'package:radio_horizon/radio_horizon.dart';
import 'package:radio_horizon/src/checks.dart';
import 'package:radio_horizon/src/helpers/random_string.dart';
import 'package:radio_horizon/src/models/song_recognition/current_station_info.dart';
import 'package:retry/retry.dart';

Expand Down Expand Up @@ -148,6 +149,95 @@ ChatCommand:radio-play: {
(translations) => translations.commands.radio.children.play.command,
),
),
ChatCommand(
_enPlayCommand.command,
_enPlayCommand.description,
id('radio-play-random', (
IChatContext context,
) async {
context as InteractionChatContext;
final commandTranslations =
getCommandTranslations(context).radio.children.playRandom;

await context.respond(
MessageBuilder.content(
commandTranslations.searching,
),
);

final radios = await _radioBrowserClient.getStationsByName(
name: getRandomString(1),
parameters: const InputParameters(limit: 10),
);

final randomIndex = math.Random().nextInt(radios.items.length);
final radio = radios.items[randomIndex];

_logger.info(
'''
ChatCommand:radio-play-random: {
'guild': ${context.guild?.id.toString() ?? 'null'},
'guild_name': ${context.guild?.name ?? 'null'},
'guild_preferred_locale': ${context.guild?.preferredLocale ?? 'null'},
'channel': ${context.channel.id},
'user': ${context.member?.id.toString() ?? 'null'},
}''',
);

await connectIfNeeded(context, replace: true);

final node = MusicService.instance.cluster
.getOrCreatePlayerNode(context.guild!.id);

await _radioBrowserClient.clickStation(
uuid: radio.stationUUID,
);

final result = await node.searchTracks(radio.urlResolved ?? radio.url);
if (result.tracks.isEmpty) {
await context.respond(
MessageBuilder.content(
commandTranslations.errors.noResults,
),
);
return;
}

final track = result.tracks.first;
node
..players[context.guild!.id]!.queue.clear()
..play(
context.guild!.id,
track,
replace: true,
requester: context.member!.id,
channelId: context.channel.id,
).startPlaying();

await SongRecognitionService.instance.setCurrentRadio(
context.guild!.id,
context.member!.voiceState!.channel!.id,
context.channel.id,
radio,
);

final embed = EmbedBuilder()
..color = getRandomColor()
..title = commandTranslations.startedPlaying
..description = commandTranslations.startedPlayingDescription(
radio: radio.name,
mention: context.member?.mention ?? '(Unknown)',
);

await context.respond(MessageBuilder.embed(embed));
}),
localizedDescriptions: localizedValues(
(translations) => translations.commands.radio.children.play.description,
),
localizedNames: localizedValues(
(translations) => translations.commands.radio.children.play.command,
),
),
ChatCommand(
_enRecognizeCommand.command,
_enRecognizeCommand.description,
Expand Down
12 changes: 12 additions & 0 deletions lib/src/helpers/random_string.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'dart:math';

const chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoP' // pragma: allowlist secret
'pQqRrSsTtUuVvWwXxYyZz1234567890'; // pragma: allowlist secret
final rnd = Random();

String getRandomString(int length) => String.fromCharCodes(
Iterable.generate(
length,
(_) => chars.codeUnitAt(rnd.nextInt(chars.length)),
),
);

0 comments on commit 83c26e0

Please sign in to comment.