lib/infoboxer.rb
# frozen_string_literal: true
# Main client module for entire infoboxer functionality. If you're lucky,
# there's no other classes/modules you need to instantiate or call
# directly. You just do:
#
# ```ruby
# Infoboxer.wp.get('List of radio telescopes')
# # or
# Infoboxer.wikiquote.get('Vonnegut')
# ```
# ...and have fully navigable Wiki information.
#
# Please read [wiki](http://github.com/molybdenum-99/infoboxer/wiki)
# for extensive [showcases](https://github.com/molybdenum-99/infoboxer/wiki/Showcase)
# and usage recommendations.
#
# Here's main components list, which also can serve as a TOC for
# Infoboxer's functionality (we suggest to read their docs in this order):
#
# * {Tree} -- nodes, of which Wikipedia AST is consisting; you'll be
# interested in basic {Tree::Node} functionality, as well as node
# classes list (which is useful for navigation);
# * {Navigation} -- how to navigate the tree you have, basic way
# (children, parents, siblings) and hi-level shortcuts way (like
# all unnumbered list items in second level-3 section);
# * {Templates} -- the most advanced data extraction from wikipedia definitely
# needs your undestanding of this (rather complicated) topic.
#
# You also may be interested in (though may be never need to use them directly):
#
# * {MediaWiki} client class;
# * {Parser} -- which, you know, parses.
#
# **NB** `Infoboxer` module can also be included in other classes, like
# this:
#
# ```ruby
# class MyDataGrabber
# include Infoboxer
#
# def initialize
# wikipedia.get('Argentina')
# end
# end
# ```
#
module Infoboxer
# @private
WIKIA_API_URL = 'http://%s.wikia.com/api.php'
WIKIMEDIA_PROJECTS = {
wikipedia: 'wikipedia.org',
wikivoyage: 'wikivoyage.org',
wikiquote: 'wikiquote.org',
wiktionary: 'wiktionary.org',
wikibooks: 'wikibooks.org',
wikinews: 'wikinews.org',
wikiversity: 'wikiversity.org',
wikisource: 'wikisource.org'
}.freeze
WIKIMEDIA_COMMONS = {
commons: 'commons.wikimedia.org',
species: 'species.wikimedia.org',
}.freeze
def wikis
@wikis ||= {}
end
# Includeable version of {Infoboxer.wiki}
def wiki(api_url, **options)
wikis[api_url] ||= MediaWiki.new(api_url, **options)
end
class << self # rubocop:disable Lint/EmptyClass -- that's for YARD!
# @!method wiki(api_url, options = {})
# Default method for creating MediaWiki API client.
#
# @param api_url should be URL of api.php for your MediaWiki
# @param options list of options.
# The only recognized option for now, though, is
# * `:user_agent` (also aliased as `:ua`) -- custom User-Agent header.
# @return [MediaWiki] an instance of API client, which you can
# further use like this:
#
# ```ruby
# Infoboxer.wiki('some_url').get('Some page title')
# ```
# @!method wikipedia(lang = 'en', options = {})
# Shortcut for creating Wikipedia client.
#
# @param lang two-character code for language version
# @param options (see #wiki for list of options)
# @return [MediaWiki]
# @!method commons(options = {})
# Shortcut for creating [WikiMedia Commons](https://commons.wikimedia.org/) client.
#
# @param options (see #wiki for list of options)
# @return [MediaWiki]
# @!method wikibooks(lang = 'en', options = {})
# Shortcut for creating [Wikibooks](https://en.wikibooks.org/) client.
# See {wikipedia} for params explanation.
# @return [MediaWiki]
# @!method wikiquote(lang = 'en', options = {})
# Shortcut for creating [Wikiquote](https://en.wikiquote.org/) client.
# See {wikipedia} for params explanation.
# @return [MediaWiki]
# @!method wikiversity(lang = 'en', options = {})
# Shortcut for creating [Wikiversity](https://en.wikiversity.org/) client.
# See {wikipedia} for params explanation.
# @return [MediaWiki]
# @!method wikisource(lang = 'en', options = {})
# Shortcut for creating [Wikisource](https://en.wikisource.org/) client.
# See {wikipedia} for params explanation.
# @return [MediaWiki]
# @!method wikivoyage(lang = 'en', options = {})
# Shortcut for creating [Wikivoyage](http://wikivoyage.org) client.
# See {wikipedia} for params explanation.
# @return [MediaWiki]
# @!method wikinews(lang = 'en', options = {})
# Shortcut for creating [Wikinews](https://en.wikinews.org/) client.
# See {wikipedia} for params explanation.
# @return [MediaWiki]
# @!method species(options = {})
# Shortcut for creating [Wikispecies](https://species.wikimedia.org/) client.
#
# @param options (see #wiki for list of options)
# @return [MediaWiki]
# @!method wiktionary(lang = 'en', options = {})
# Shortcut for creating [Wiktionary](https://en.wiktionary.org/) client.
# See {wikipedia} for params explanation.
# @return [MediaWiki]
# @!method wikia(*domains)
# Performs request to wikia.com wikis.
#
# @overload wikia(*domains)
# @param *domains list of domains to merge, like this:
#
# ```ruby
# Infoboxer.wikia('tardis') # looks at tardis.wikia.com
# Infoboxer.wikia('tardis', 'ru') # looks in Russian version, ru.tardis.wikia.com
# ```
# If you are surprised by "reversing" list of subdomains, think of
# it as of chain of refinements (looking in "tardis" wiki, its "ru"
# version, specifically).
#
# @overload wikia(*domains, options)
# @param *domains same as above
# @param options just last of params, if it is hash
# (see {wiki} for list of options)
#
# @return [MediaWiki]
end
WIKIMEDIA_PROJECTS.each do |name, domain|
define_method name do |lang = 'en', **options|
lang, options = 'en', lang if lang.is_a?(Hash)
wiki("https://#{lang}.#{domain}/w/api.php", **options)
end
end
alias_method :wp, :wikipedia
WIKIMEDIA_COMMONS.each do |name, domain|
define_method name do |**options|
wiki("https://#{domain}/w/api.php", **options)
end
end
# Returns URL of API entry-point for a well-known Wiki-project (wikipedia, wikivoyage etc.)
# by project's name.
#
# @param symbol [Symbol] One of {WIKIMEDIA_PROJECTS} or {WIKIMEDIA_COMMONS} keys.
# @param lang [String, Symbol] Language of the project, if applicable.
# @return [String]
def url_for(symbol, lang = 'en')
if (domain = WIKIMEDIA_PROJECTS[symbol])
"https://#{lang}.#{domain}/w/api.php"
elsif (domain = WIKIMEDIA_COMMONS[symbol])
"https://#{domain}/w/api.php"
end
end
# @!method wikipedia(lang = 'en', options = {})
# Includeable version of {Infoboxer.wikipedia}
# @!method commons(options = {})
# Includeable version of {Infoboxer.commons}
# @!method wikibooks(lang = 'en', options = {})
# Includeable version of {Infoboxer.wikibooks}
# @!method wikiquote(lang = 'en', options = {})
# Includeable version of {Infoboxer.wikiquote}
# @!method wikiversity(lang = 'en', options = {})
# Includeable version of {Infoboxer.wikiversity}
# @!method wikisource(lang = 'en', options = {})
# Includeable version of {Infoboxer.wikisource}
# @!method wikivoyage(lang = 'en', options = {})
# Includeable version of {Infoboxer.wikivoyage}
# @!method wikinews(lang = 'en', options = {})
# Includeable version of {Infoboxer.wikinews}
# @!method species(options = {})
# Includeable version of {Infoboxer.species}
# @!method wiktionary(lang = 'en', options = {})
# Includeable version of {Infoboxer.wiktionary}
# Includeable version of {Infoboxer.wikia}
def wikia(*domains)
options = domains.last.is_a?(Hash) ? domains.pop : {}
wiki(WIKIA_API_URL % domains.reverse.join('.'), **options)
end
# Sets user agent string globally. Default user agent is
# {MediaWiki::UA}.
#
# User agent can also be rewriten as an option to {wiki} method (and
# its shortcuts like {wikipedia}), or by using {MediaWiki#initialize}
# explicitly.
#
def self.user_agent=(ua)
MediaWiki.user_agent = ua
end
extend self
end
require_relative 'infoboxer/version'
require_relative 'infoboxer/core_ext'
require_relative 'infoboxer/tree'
require_relative 'infoboxer/parser'
require_relative 'infoboxer/navigation'
require_relative 'infoboxer/templates'
require_relative 'infoboxer/media_wiki'
require_relative 'infoboxer/definitions/en.wikipedia.org'