WOOB – Web Outside Of Browsers

The Web Outside of Browsers Project allows users to access Internet data in a generic way without using a Web Browser.

Woob offers a common interface for accessing a variety of different Internet data sources. So rather than using a specific API to access to weather and then another to access a job boards, the Woob API/tools can be used for both of these data sources.

Woob can be used as a:

  • Python library,
  • A command line tool, or by
  • Bash scripting

In this blog I wanted to document my Linux notes on:

  • basic command line tool usage
  • Bash/Python examples for getting weather data
  • Bash/Python examples for playing Internet streaming music

Note: WOOB is in development so features may change. Also there is a large list of application modules, but at present most are European based.

Getting Started

To install woob:

$ pip install woob

Once woob is installed a list of features can be shown by entering woob:

$ woob
usage: woob [--version] <command> [<args>]

Use one of this commands:
   bands           display bands and suggestions
   bank            manage bank accounts
   bill            get/download documents and bills
   books           manage rented books
   bugtracker      manage bug tracking issues
   calendar        see upcoming events
   cinema          search movies and persons around cinema
   cli             call a method on backends
   config          manage backends or register new accounts
   contentedit     manage websites content
   dating          interact with dating websites
   debug           debug backends
   gallery         browse and download web image galleries
   gauge           display sensors and gauges values
   geolocip        geolocalize IP addresses
   housing         search for housing
   job             search for a job
   lyrics          search and display song lyrics
   money           import bank accounts into Microsoft Money
   msg             send and receive message threads
   parcel          manage your parcels
   paste           post and get pastes from pastebins
   pricecompare    compare products
   radio           search, show or listen to radio stations
   recipes         search and consult recipes
   repos           manage a woob repository
   rpg             manage RPG data
   shop            obtain details and status of e-commerce orders
   smtp            daemon to send and check messages
   subtitles       search and download subtitles
   torrent         search and download torrents
   translate       translate text from one language to another
   travel          search for train stations and departures
   video           search and play videos
   weather         display weather and forecasts

For more information about a command, use:
   $ man woob-<command>
or
   $ woob <command> --help

Each features has a backend (database) associated with it. For example to define the weather.com backend for the weather command:

$ woob weather
Warning: there is currently no configured backend for weather
Do you want to configure backends? (Y/n): y

Available modules:
1) [ ] ilmatieteenlaitos   Get forecasts from the Ilmatieteenlaitos.fi website
2) [ ] lameteoagricole   lameteoagricole website
3) [ ] meteofrance       Get forecasts from the MeteoFrance website
4) [ ] weather           Get forecasts from weather.com
a) --all--               install all backends
q) --stop--

Select a backend to create (q to stop): 4
Backend "weather" successfully added.

If a backend needs to be removed, for example meteofrance, use the backend remove command:

$ wood weather backend remove meteofrance

To check which backends are defined, use the backend list command:

$ woob weather backend list
Enabled: weather

$ woob radio backend list
Enabled: freeteknomusic, somafm

Using the Weather Command

Woob offers a number of weather modules. A good generic option is weather.com.

To get started at the command line, enter: woob weather

$ woob weather 
Welcome to weather v3.0

Copyright(C) 2010-2022 Romain Bignon
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Type "help" to display available commands.

Loaded backends: weather

weather> help
Weather Commands:
    cities PATTERN
    current CITY_ID
    debug
    forecasts CITY_ID

Woob Commands:
    formatter [list | FORMATTER [COMMAND] | option OPTION_NAME [on | off]]
    select [FIELD_NAME]... | "$direct" | "$full"
    ls [-d] [-U] [PATH]
    cd [PATH]
    condition [EXPRESSION | off]
    count [NUMBER | off]
    backends [ACTION] [BACKEND_NAME]...
    quit
    logging [LEVEL]

Type "help <command>" for more info about a command.

The first step is to search for a city with the cities option. Once a city is found the id (1-20) is used to show the current weather and the future forecast.

The example below searches for Toronto. The first item (Toronto, Ontario, Canada) is selected (current 1) to show the present Toronto weather. Toronto’s future weather can be checked with the forecast command (forecast 1).

Bash Scripting for Weather

The command line utility can be used with Bash script, (For more info on the interface).

A scripting example to show the current and forecast weather for Toronto (the first item in the list):

$ # use the -n 1 option to get the first item
$ woob weather cities 'Toronto' -n 1
d8ccf908e3c4c748e232720575df7cdbca6e0f1b412bca8595d8a28d0c28e8bc@weather — Toronto, Ontario, Canada

$ # get the id (first string) and save to a variable
$ city_id=$(woob weather cities 'Toronto' -n 1 | awk '{print $1}')

$ # pass the city id to get the weather current
$ woob weather current $city_id 
2022-12-08: -1 °C - 1030.2hPa (Rising) - humidity 73% - feels like -4 °C/24 °F - Fair

An example is to get the current weather for a place and show it as a Linux system tray notification:

$ # Create a notification note with current weather information
$ my_city="Sauble Beach"
$ city_id=$(woob weather cities "$my_city" -n 1 | awk '{print $1}')
$ notify-send -t 1000000 "$my_city" "$(woob weather current $city_id )

To show the long term forecast information in a Zenity dialog:

$ # Create an Info Dialog with weather forecast information
$ my_city="Sauble Beach"
$ city_id=$(woob weather cities "$my_city" -n 1 | awk '{print $1}')
$ wf=$(woob weather forecast $city_id)
$ zenity --width=650 --info --text="$wf" --title="$my_city"

Python Woob Weather Example

A Python example to select the first city in a list and then show the forecast would be:

#!/usr/bin/python3
#
# wweather.py - Search for weather forecast for a place
#
from woob.core import Woob
from woob.capabilities.weather import CapWeather

w=Woob()
w.load_backends(CapWeather)

# Find the id for a location
for city in w.iter_city_search("Sauble Beach"):
    # stop at first hit    
    print(city.id, city.name)
    break

# Get the Forecast for that location
for w0 in w.iter_forecast(city.id):
    print("Date:", w0.date)
    print("Forecast:", w0.text)
    print("High:", w0.high)
    print("Low", w0.low, "\n")

For more information on the Weather calls.

Using the Radio Command

There are a number of radio modules to choose from. The first step is to add at least one module:

$ woob radio
Warning: there is currently no configured backend for radio
Do you want to configure backends? (Y/n): y

Available modules:
1) [ ] audioaddict       Internet radios powered by audioaddict.com services
2) [ ] bandcamp          Bandcamp music website
3) [ ] freeteknomusic    freeteknomusic website
4) [ ] ina               INA French TV video archives
5) [ ] nectarine         Nectarine Demoscene Radio
6) [ ] nova              Nova French radio
7) [ ] ouifm             OÜI FM French radio
8) [ ] radiofrance       Radios of Radio France: Inter, Info, Bleu, Culture, Musique, FIP, Le Mouv'
9) [ ] somafm            SomaFM web radio
10) [ ] virginradio       VirginRadio french radio
a) --all--               install all backends
q) --stop--

Select a backend to create (q to stop): 9
Backend "somafm" successfully added.

After one of more radio modules are added, you can search for radio stations that play a genre:

$ woob radio
Welcome to radio v3.0

Type "help" to display available commands.

Loaded backends: freeteknomusic, somafm

radio> search radio trance
id: thetrip@somafm
title: The Trip
description: Progressive house / trance. Tip top tunes.
current: B With U (Salinas' Dub Mix) - Tommyboy And Soultan Feat. Zara
streams: ['130Kbps/aac' ('http://somafm.com/thetrip130.pls'), 'fast/mp3' ('http://somafm.com/thetrip.pls'), '64Kbps/aacp' ('http://somafm.com/thetrip64.pls'), '32Kbps/aacp' ('http://somafm.com/thetrip32.pls')]

radio:/search> play 1

For this radio station search of “trance” only 1 station was found, so play 1 is used to listen to that station. (Note: if 3 were returned then you could listen to the third station by: play 3).

Bash Scripting for Internet Radio

There are some woob options that will make scripting a little easier. Some genres like “rock” or “ambient” will return too many hits, so the -n option can be set to limit the number of returned items. The -s option will return only selected fields.

$ # Show the id and description 
$ #  for the first 2 ambient station 
$ woob radio search radio "ambient" -s id,description -n 2
id: deepspaceone@somafm
description: Deep ambient electronic, experimental and space music. For inner and outer space exploration.

id: groovesalad@somafm
description: A nicely chilled plate of ambient/downtempo beats and grooves.

An example script (wlisten.sh) takes a music genre entered on the command line and then finds and plays the first related station.

#!/bin/bash
#
# wlisten.sh - find a Woob Radio station and play it
#
echo -e "\nWoob Internet Radio Player\n"

echo -n "Enter a type of Music to listen to: " 
read mtype
echo "Now playing : $mtype music ..."
woob radio play $(woob radio search radio "$mtype" -n 1 -s id | awk '{print $2}' )

To run this script (wlisten.sh) to play a reggae station:

$ bash wlisten.sh

Woob Internet Radio Player

Enter a type of Music to listen to: reggae
Now playing : reggae music ...

This example only uses the first returned station. By using a couple of Zenity list dialongs a Bash script can be created to present a list of preset genres, then the user can select a specific station.

#!/bin/bash
#
# wradio.sh - find a Woob Radio station and play it
#
mtype=$(zenity --title="Play Internet Radio" \
	--list --height=500 --width=300 --column="Music Type" \
        80s Ambient Dance House Jazz Pop Rock Reggae Top Trance) 
# if a music type is selected then get stations
echo "Music Type: $mtype"
if [[ -n "$mtype" ]] ; then
  stn=$(woob radio search radio $mtype -f radio_list  | zenity --list \
    --title="Select Radio Station" \
    --column=station --column=description --width=900 --height=300)
  # Get the station ID, its the 1st part of the station string
  stn_id="${stn%%—*}"
  # If the station string is not empty, play the station
  if [[ -n "$stn_id" ]]  ; then
    echo "Station Id: $stn_id"
    woob radio play $stn_id
  fi
fi

Python Woob Radio Example

To get a selection of radio stations for a genre:

from woob.core import Woob
from woob.capabilities.radio import CapRadio

w = Woob()
w.load_backends(CapRadio)

genre="rock"

for stns in w.iter_radios_search(genre):
        print(stns.id, stns.title, stns.description, "\n")

See the Woob tech api docs for more details on the radio API.

A Python Tkinter GUI example to select a genre and then play a radio station:

#!/usr/bin/python3
#
# wradio.py - Tkinter GUI for Woob Radio    
#
from tkinter import *
from tkinter import ttk
import subprocess
from woob.core import Woob
from woob.capabilities.radio import CapRadio

w = Woob()
w.load_backends(CapRadio)

# Fill the tree with genre stations
def show_stations():
    genre = cbo.get()
    tree.delete(*tree.get_children())
    # Insert Rows into tree based on found radio stations
    for stns in w.iter_radios_search(genre):
        tree.insert('','end',text=stns.id,values=(stns.id, stns.title, stns.description))    

# Play selected station
def tree_getitem(a):
    curItem = tree.focus()
    stn_info=tree.item(curItem) # station is dictionary variable
    thestn=stn_info['text'] # get the station id
    p=subprocess.Popen(["killall", "woob"])
    p=subprocess.Popen(["killall", "mpv"])
    if thestn != "":
        labelText.set("Playing Station: " + thestn)
        p=subprocess.Popen(["woob", "radio", "play", thestn])

def stop_music():
    labelText.set("")
    p=subprocess.Popen(["killall", "woob"])
    p=subprocess.Popen(["killall", "mpv"])
    

# Create an instance of tkinter frame
root = Tk()
genre="Rock"
root.title('Play Internet Radio Stations')
root.geometry('900x300')

# Create a listbox of station genres
label1 = ttk.Label(text = "Enter a genre: ").grid(row=0,column=0)
cbo = ttk.Combobox(root,height = 1)
genres= {"80s","Ambient", "Dance", "House","Jazz","Pop","Rock", "Reggae","Trance"}
cbo['value'] = [m for m in genres]
cbo.grid(row=0, column=1)

# Create a button to update station tree
bt_update = ttk.Button(root,text="Select Genre", command=show_stations)
bt_update.grid(row=0, column=2)

# Create a tree list with 3 columns
tree = ttk.Treeview(root, column=("Id","Station", "Desciption"), show='headings') 
tree.column("#1", width=100)
tree.heading("#1", text="ID")
tree.column("#2", width=200)
tree.heading("#2", text="Station")
tree.column("#3", width=600)
tree.heading("#3", text="Description")
tree.grid(row=1, column=0, columnspan=3)
tree.bind('<ButtonRelease-1>', tree_getitem)

# Create a label to show station being played
labelText = StringVar()
label2 = ttk.Label(textvariable=labelText).grid(row=2,column=0)

# Add a button to start and stop music
bt_stop = ttk.Button(root,text="Stop Music", command=stop_music)
bt_stop.grid(row=2,column=1)

root.mainloop()
    

Summary

The Woob project has a lot of potential, however because it is still in the development stage it can be a little challenging to use.

Due to the lack of examples, I found that I was able to get up and running faster with Bash scripts rather than Python. To build a Bash script I would first test what I wanted to do in the online tool, then I would mimic this in Bash.