Skip to content

Instantly share code, notes, and snippets.

@SwagDevOps
Last active April 8, 2021 22:17
Show Gist options
  • Select an option

  • Save SwagDevOps/87aff6f0b44c7779f97a5fd9eaf12c28 to your computer and use it in GitHub Desktop.

Select an option

Save SwagDevOps/87aff6f0b44c7779f97a5fd9eaf12c28 to your computer and use it in GitHub Desktop.

Revisions

  1. SwagDevOps revised this gist Jul 19, 2020. 1 changed file with 1 addition and 3 deletions.
    4 changes: 1 addition & 3 deletions transistor.rb
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,6 @@
    #!/usr/bin/env ruby
    # -*- coding: utf-8 -*-

    autoload(:Shellwords, 'shellwords')
    autoload(:YAML, 'yaml')
    autoload(:Pathname, 'pathname')
    autoload(:Etc, 'etc')
    @@ -69,9 +68,8 @@ def completion
    '_%{prog_name}_complete() {',
    ' local curr="${COMP_WORDS[COMP_CWORD]}"',
    ' local size="${#COMP_WORDS[@]}"',
    ' local words=$(%{executable} -?)',
    ' test "$size" -lt 3 && {',
    ' COMPREPLY=($(compgen -W "$words" -- "$curr"))',
    ' COMPREPLY=($(compgen -W "$(%{executable} -?)" -- "$curr"))',
    ' }',
    ' return 0',
    '}',
  2. SwagDevOps revised this gist Jul 19, 2020. 2 changed files with 14 additions and 4 deletions.
    16 changes: 12 additions & 4 deletions transistor.rb
    Original file line number Diff line number Diff line change
    @@ -51,6 +51,11 @@ def call(station: nil)
    command_for(station).yield_self { |command| exec(*command) }
    end

    # @return [Pathname]
    def executable
    Pathname.new(__FILE__).realpath
    end

    # Provide bash completion.
    #
    # Sample of use:
    @@ -64,7 +69,7 @@ def completion
    '_%{prog_name}_complete() {',
    ' local curr="${COMP_WORDS[COMP_CWORD]}"',
    ' local size="${#COMP_WORDS[@]}"',
    ' local words=\'%{words}\'',
    ' local words=$(%{executable} -?)',
    ' test "$size" -lt 3 && {',
    ' COMPREPLY=($(compgen -W "$words" -- "$curr"))',
    ' }',
    @@ -73,8 +78,8 @@ def completion
    'complete -F _%{prog_name}_complete %{prog_name}',
    ].join("\n").yield_self do |s|
    (s % {
    words: stations.keys.map(&:to_s).join(' '),
    prog_name: Pathname.new(__FILE__).basename('.*').to_s
    executable: executable,
    prog_name: executable.basename('.*').to_s
    }).freeze
    end
    end
    @@ -155,8 +160,11 @@ def load_config(filepath = nil)
    # Execution ----------------------------------------------------------
    if __FILE__ == $0
    Transistor.new.yield_self do |radio|
    if ARGV[0] == '-#'
    case ARGV[0]
    when '-#'
    radio.completion.tap { |s| puts(s) }
    when '-?'
    radio.stations.keys.map(&:to_s).sort.join("\n").tap { |s| puts(s) }
    else
    radio.call(station: ARGV[0]) if __FILE__ == $0
    end
    2 changes: 2 additions & 0 deletions transistor.yml
    Original file line number Diff line number Diff line change
    @@ -4,6 +4,8 @@ cache:
    enabled: true
    default: 100
    initial: 50
    msg:
    level: statusline=status
    stations:
    pulsradio: 'http://www.pulsradio.com/pls/puls-adsl.m3u'
    q-dance: 'https://19983.live.streamtheworld.com/Q_DANCE.mp3'
  3. SwagDevOps revised this gist Jul 19, 2020. 1 changed file with 42 additions and 4 deletions.
    46 changes: 42 additions & 4 deletions transistor.rb
    Original file line number Diff line number Diff line change
    @@ -9,9 +9,11 @@
    # Sample of use:
    #
    # ```sh
    # transistor.rb # Play default (first)
    # transistor.rb pulsradio # Play station by name
    # transistor.rb 0 # Play station by index
    # transistor.rb # Play default (first)
    # transistor.rb pulsradio # Play station by name
    # transistor.rb 0 # Play station by index
    # transistor -\# # Print bash completion
    # eval "$(transistor -\#)" # Load completion
    # ```
    class Transistor
    # @return [Hash{Symbol => Object}]
    @@ -49,6 +51,34 @@ def call(station: nil)
    command_for(station).yield_self { |command| exec(*command) }
    end

    # Provide bash completion.
    #
    # Sample of use:
    # ```sh
    # eval "$(transistor -\#)"
    # ```
    #
    # @return [String]
    def completion
    [
    '_%{prog_name}_complete() {',
    ' local curr="${COMP_WORDS[COMP_CWORD]}"',
    ' local size="${#COMP_WORDS[@]}"',
    ' local words=\'%{words}\'',
    ' test "$size" -lt 3 && {',
    ' COMPREPLY=($(compgen -W "$words" -- "$curr"))',
    ' }',
    ' return 0',
    '}',
    'complete -F _%{prog_name}_complete %{prog_name}',
    ].join("\n").yield_self do |s|
    (s % {
    words: stations.keys.map(&:to_s).join(' '),
    prog_name: Pathname.new(__FILE__).basename('.*').to_s
    }).freeze
    end
    end

    class << self
    def config_name
    'transistor'
    @@ -123,4 +153,12 @@ def load_config(filepath = nil)
    end

    # Execution ----------------------------------------------------------
    Transistor.new.call(station: ARGV[0]) if __FILE__ == $0
    if __FILE__ == $0
    Transistor.new.yield_self do |radio|
    if ARGV[0] == '-#'
    radio.completion.tap { |s| puts(s) }
    else
    radio.call(station: ARGV[0]) if __FILE__ == $0
    end
    end
    end
  4. SwagDevOps revised this gist Jul 18, 2020. 1 changed file with 1 addition and 7 deletions.
    8 changes: 1 addition & 7 deletions transistor.rb
    Original file line number Diff line number Diff line change
    @@ -46,7 +46,7 @@ def stations
    end

    def call(station: nil)
    command_for(station).yield_self { |command| sh(*command) }
    command_for(station).yield_self { |command| exec(*command) }
    end

    class << self
    @@ -78,12 +78,6 @@ def resolve(station)
    end.to_sym
    end

    def sh(*args)
    Shellwords.join(args.dup.reject { |item| item.is_a?(Hash) }).yield_self do |command|
    system(*args) || (-> { raise command }).call
    end
    end

    # @return [Array<String>]
    def command_for(station)
    [
  5. SwagDevOps revised this gist Jul 18, 2020. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion transistor.rb
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,6 @@
    autoload(:Pathname, 'pathname')
    autoload(:Etc, 'etc')


    # Sample of use:
    #
    # ```sh
  6. SwagDevOps revised this gist Jul 18, 2020. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions transistor.rb
    Original file line number Diff line number Diff line change
    @@ -15,6 +15,9 @@
    # transistor.rb 0 # Play station by index
    # ```
    class Transistor
    # @return [Hash{Symbol => Object}]
    attr_reader :config

    def initialize(config: nil)
    load_config(config).tap do |c|
    @config = {
    @@ -113,9 +116,6 @@ def command_for(station)
    ].compact.map(&:freeze)
    end

    # @type [Hash{Symbol => String}]
    attr_writer :stations

    def load_config(filepath = nil)
    lambda do
    return Pathname.new(filepath) unless filepath.nil?
  7. SwagDevOps created this gist Jul 18, 2020.
    133 changes: 133 additions & 0 deletions transistor.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,133 @@
    #!/usr/bin/env ruby
    # -*- coding: utf-8 -*-

    autoload(:Shellwords, 'shellwords')
    autoload(:YAML, 'yaml')
    autoload(:Pathname, 'pathname')
    autoload(:Etc, 'etc')


    # Sample of use:
    #
    # ```sh
    # transistor.rb # Play default (first)
    # transistor.rb pulsradio # Play station by name
    # transistor.rb 0 # Play station by index
    # ```
    class Transistor
    def initialize(config: nil)
    load_config(config).tap do |c|
    @config = {
    screensaver: c.fetch(:screensaver, false),
    stations: c.fetch('stations') do
    { pulsradio: 'http://www.pulsradio.com/pls/puls-adsl.m3u' }
    end.transform_keys(&:to_sym),
    msg: {
    color: true,
    level: 'all=v',
    }.merge(c['msg'].to_h.transform_keys(&:to_sym)),
    cache: {
    enabled: false,
    default: 100,
    initial: 50 }.merge(c['cache'].to_h.transform_keys(&:to_sym)),
    'user-agent': c['user-agent'] || [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0)',
    'Gecko/20100101 Firefox/76.0'
    ].join(' ')
    }.transform_values(&:freeze).freeze
    end
    end

    # @type [Hash{Symbol => String}]
    def stations
    config.fetch(:stations)
    end

    def call(station: nil)
    command_for(station).yield_self { |command| sh(*command) }
    end

    class << self
    def config_name
    'transistor'
    end
    end

    protected

    # @type [Hash{Symbol => Object}]
    attr_reader :config

    # @param [String|Symbol|nil] station
    #
    # @return [Symbol]
    # @raise [RuntimeError]
    def resolve(station)
    station.tap do
    return stations.keys.fetch(0) if station.nil?

    if station.is_a?(Integer) or station.match(/^[0-9]+$/)
    return stations.keys.fetch(station.to_i)
    end

    unless stations.key?(station.to_sym)
    raise "Can not resolve #{station.inspect}"
    end
    end.to_sym
    end

    def sh(*args)
    Shellwords.join(args.dup.reject { |item| item.is_a?(Hash) }).yield_self do |command|
    system(*args) || (-> { raise command }).call
    end
    end

    # @return [Array<String>]
    def command_for(station)
    [
    'mpv',
    '--no-video',
    '--ytdl=no',
    config[:screensaver].yield_self do |v|
    "--stop-screensaver=#{v ? 'no' : 'yes'}"
    end,
    config[:msg][:color].yield_self do |v|
    "--msg-color=#{v ? 'yes' : 'no'}"
    end,
    config[:msg][:level].yield_self do |v|
    v ? "--msg-level=#{v}" : nil
    end,
    config.fetch(:'user-agent').yield_self do |v|
    v ? "--user-agent=#{v}" : nil
    end,
    config[:cache][:enabled].yield_self do |v|
    "--cache=#{v ? 'yes' : 'no'}"
    end,
    config[:cache][:default].yield_self do |v|
    v ? "--cache-default=#{v}" : nil
    end,
    config[:cache][:initial].yield_self do |v|
    v ? "--cache-initial=#{v}" : nil
    end,
    resolve(station).yield_self { |k| stations.fetch(k.to_sym) },
    ].compact.map(&:freeze)
    end

    # @type [Hash{Symbol => String}]
    attr_writer :stations

    def load_config(filepath = nil)
    lambda do
    return Pathname.new(filepath) unless filepath.nil?

    ENV.fetch('XDG_CONFIG') do
    Pathname.new(Etc.getpwnam(Etc.getlogin).dir).join('.config')
    end.yield_self { |fp| Pathname.new(fp) }.join("#{self.class.config_name}.yml")
    end.call.yield_self do |file|
    file.file? and file.readable? ? YAML.safe_load(file.read) : {}
    end
    end
    end

    # Execution ----------------------------------------------------------
    Transistor.new.call(station: ARGV[0]) if __FILE__ == $0
    9 changes: 9 additions & 0 deletions transistor.yml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    # ~/.config/transistor.yml
    ---
    cache:
    enabled: true
    default: 100
    initial: 50
    stations:
    pulsradio: 'http://www.pulsradio.com/pls/puls-adsl.m3u'
    q-dance: 'https://19983.live.streamtheworld.com/Q_DANCE.mp3'