radio-rs

Place a description here.
git clone git://git.alex.balgavy.eu/reponame.git
Log | Files | Refs

commit f909b8cbc4f0ca007918065bbaddfd8adbcc95c9
parent 44fd2dfbe476a8f13b067f8fbd583a39d777863a
Author: Alex Balgavy <alex@balgavy.eu>
Date:   Sat,  4 Jun 2022 22:36:15 +0200

Add ruby files that I still need to rewrite

Diffstat:
Msrc/config.rs | 2+-
Msrc/main.rs | 19+++++++++++--------
Asrc/radio/radiogarden.rb | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/radio/sounds_of_earth.rb | 32++++++++++++++++++++++++++++++++
Asrc/radio/subreddit.rb | 43+++++++++++++++++++++++++++++++++++++++++++
Msrc/screen.rs | 19++++++++-----------
6 files changed, 148 insertions(+), 20 deletions(-)

diff --git a/src/config.rs b/src/config.rs @@ -19,7 +19,7 @@ pub struct Item { pub website: String, pub url: Option<String>, pub mpc_load_option: Option<MpcLoadOptions>, - pub radios: Option<Vec<Item>> + pub radios: Option<Vec<Item>>, } pub fn read_config() -> ConfigData { diff --git a/src/main.rs b/src/main.rs @@ -2,10 +2,10 @@ mod config; mod radio; mod screen; mod tunein; +use config::*; use radio::*; use std::process::exit; use tunein::*; -use config::*; fn choose_radio(radios: &Vec<Item>) -> &Item { loop { let choices: Vec<String> = radios @@ -15,18 +15,21 @@ fn choose_radio(radios: &Vec<Item>) -> &Item { let (choice_i, _) = match screen::list_menu(&*choices) { Some((i, s)) => (i, s), - None => continue + None => continue, }; let chosen_radio = match radios[choice_i].url { Some(_) => &radios[choice_i], None => { - let choices: Vec<String> = radios[choice_i].radios.as_ref().unwrap() + let choices: Vec<String> = radios[choice_i] + .radios + .as_ref() + .unwrap() .iter() .map(|x| format!("{} ({})", x.name, x.website)) .collect(); let (choice_i, _) = match screen::list_menu(&*choices) { Some((i, s)) => (i, s), - None => continue + None => continue, }; &radios[choice_i] } @@ -37,10 +40,10 @@ fn choose_radio(radios: &Vec<Item>) -> &Item { fn main() { let data = config::read_config(); assert!(data - .config - .radios - .iter() - .all(|x| (x.url.is_some() && x.mpc_load_option.is_some()) || (x.radios.is_some()))); + .config + .radios + .iter() + .all(|x| (x.url.is_some() && x.mpc_load_option.is_some()) || (x.radios.is_some()))); let top_radios = &data.config.radios; let chosen_radio = choose_radio(top_radios); diff --git a/src/radio/radiogarden.rb b/src/radio/radiogarden.rb @@ -0,0 +1,53 @@ +# TODO: convert to rust +class RadioGarden < Radio + require 'json' + require 'open-uri' + require 'cgi' + + def initialize(_) + @base_url = 'https://radio.garden/api' + puts 'No radio found, please try again.' while (retrieved_channels = search_channels).empty? + channels = parse_channels(retrieved_channels) + selected_channel = choose_from_list(channels, channels.map { |c| c[:name] }) while selected_channel.nil? + @channel = get_channel_link(selected_channel) + super() + rescue Interrupt + @channel = nil + end + + def play + if @player == 'mpc' + system 'mpc', 'clear', 1 => '/dev/null' + system 'mpc', 'add', @channel + end + super @channel + end + + private + + def search_channels + print 'Enter radio search: ' + query = gets.chomp + URI.parse("#{@base_url}/search?q=#{CGI.escape query}").open do |response| + JSON.parse(response.read)['hits']['hits'] + end + rescue OpenURI::HTTPError + [] + end + + def get_channel_link(selected_channel) + # Will redirect + @channel = URI.parse("#{@base_url}/ara/content/listen/#{selected_channel[:id]}/channel.mp3").open(redirect: false) + rescue OpenURI::HTTPRedirect => e + @channel = e.uri.to_s.gsub(/\?listening-from.*/, '') + rescue OpenURI::HTTPError + @channel = None + end + + def parse_channels(retrieved_channels) + retrieved_channels.inject([]) do |channels, c| + channels << { name: "#{c['_source']['title']} (#{c['_source']['subtitle']})", + id: c['_source']['channelId'] } + end + end +end diff --git a/src/radio/sounds_of_earth.rb b/src/radio/sounds_of_earth.rb @@ -0,0 +1,32 @@ +# TODO: convert to rust +class SoundsOfEarth < Radio + require 'json' + require 'open-uri' + + def initialize(_) + channels = retrieve_channels + @channel = choose_from_list(channels.map { |c| c[:link] }, channels.map { |c| c[:name] }) while @channel.nil? + super() + rescue Interrupt + @channel = nil + end + + def play + if @player == 'mpc' + system 'mpc', 'clear', 1 => '/dev/null' + system 'mpc', 'add', @channel + end + super @channel + end + + private + + def retrieve_channels + URI('https://soundsofearth.eco/regions.json').open do |response| + streams = JSON.parse(response.read)['results'] + streams.map { |stream| { name: "#{stream['name']} (#{stream['description']})", link: stream['sound'] } } + end + rescue OpenURI::HTTPError + [] + end +end diff --git a/src/radio/subreddit.rb b/src/radio/subreddit.rb @@ -0,0 +1,43 @@ +# TODO: convert to rust +class Subreddit < Radio + require 'json' + require 'open-uri' + require 'shellwords' + + def initialize(_) + puts 'Subreddit has no music posts or does not exist.' while (posts = retrieve_subreddit_posts).empty? + @links = extract_post_links(posts) + super() + rescue Interrupt + @channel = nil + end + + def play + puts "Number of tracks: #{@links.length}" + # TODO: support mpd + system("mpv --vid=no --volume=50 -- #{@links.map { |l| l[:url] }.shelljoin}") + end + + private + + def retrieve_subreddit_posts + print 'Enter subreddit name: ' + sub = gets.chomp + url = "https://www.reddit.com/r/#{sub}/top.json?t=month&limit=100&show=all" + URI.parse(url).open('User-Agent' => 'ruby/2.7', 'Accept' => 'application/json') do |response| + @channel = sub + JSON.parse(response.read)['data']['children'] + end + rescue OpenURI::HTTPError + [] + end + + def extract_post_links(posts) + posts.each_with_object([]) do |post, links| + p = post['data'] + if !p['is_self'] && p['post_hint'] != 'image' + links.append(title: p['title'], url: p['url'], reddit: "https://reddit.com#{p['permalink']}") + end + end + end +end diff --git a/src/screen.rs b/src/screen.rs @@ -22,7 +22,6 @@ fn prompt(prompt: &str) -> String { } } - pub fn list_menu(list: &[String]) -> Option<(usize, String)> { let mut message = None; loop { @@ -44,17 +43,15 @@ pub fn list_menu(list: &[String]) -> Option<(usize, String)> { let n = match trimmed.parse::<usize>() { Ok(n) => n, - _ => { - match trimmed { - "q" | "quit" => { - return None; - } - _ => { - message = Some("Not a number!"); - continue; - } + _ => match trimmed { + "q" | "quit" => { + return None; + } + _ => { + message = Some("Not a number!"); + continue; } - } + }, }; if n == 0 || n > list.len() { message = Some("choice out of range");