gutenfinder

package module
v0.0.0-...-d81bb10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 30, 2018 License: MIT Imports: 41 Imported by: 0

README

Gutenfinder: search widget for Project Gutenberg

Gutenfinder is a little project to make a search widget for Project Gutenberg.

It is under development.

CLI examples:

Serve a webapp on localhost, port 8080:

$ gutenfinder web serve \
	--postgres="user=username dbname=gutenfinder host=dbhost sslmode=disable" \
	--elastic="http://gutenfinder_dev_elastic:9200"

Search for eBooks on the command line:

$ gutenfinder search --term beancurd
{
	"id": 9,
	"term": "beancurd",
	"result_count": 1,
	"items": [
		{
			"id": 467,
			"ebook_id": 724,
			"ebook_title": "Have We No Rights? A frank discussion of the \"rights\" of missionaries",
			"html_snippet": "be made of a couple of\r\nplanks laid on sawhorses, and you may have to eat boiled rice, greens,\r\nand \u003cem\u003ebeancurd\u003c/em\u003e"
		}
	]
}

Results are returned based on titles, the full text of the book, and any other properties currently indexed.

Getting started

Dependencies

Install the following dependencies:

Due to an issue with the dockerized Elasticsearch, the following tweak must be made on Linux:

sudo sysctl -w vm.max_map_count=262144

This setting will be lost on reboot, but can be permanently set by adding it to /etc/etc/sysctl.conf

Initialize the project

$ ./script/init
$ ./script/download

This will download a lot of data from a Project Gutenberg archive.

Run with docker

The following sequence of commands will build and launch the app, run migrations, read the eBook catalogue, and index the eBooks on Elasticsearch.

$ ./script/docker-compose-up
$ ./script/db-migrate
$ ./script/catalogue-load-xml
$ ./script/catalogue-load-text

Credits

Johnny Morrice

I am not affiliated with Project Gutenberg in any way. This is just for fun.

License

MIT-style, see the LICENSE file.

Documentation

Overview

Package gutenfinder is an unofficial search tool for the Project Gutenberg catalogue.

Index

Constants

View Source
const (
	CatalogueUpdateEBook = CatalogueUpdateTypeID(iota)
	CatalogueUpdateAuthor
)
View Source
const (
	LogLevelNothing = LogLevel(iota)
	LogLevelError
	LogLevelWarn
	LogLevelInfo
	LogLevelDebug
)

LogLevels supported by Gutenfinder.

View Source
const (
	TextSearchResultItemTypeID
	TitleSearchResultItemTypeID
	AuthorAliasSearchResultItemTypeID
)

SearchResultItemTypeIDs supported by Gutenfinder.

View Source
const (
	EncodingUTF8 = TextEncodingID(iota)
	EncodingISO8859_1
	EncodingASCII
)

EBook text file encodings supported by Gutenfinder.

View Source
const APIResourceSearch = "/api/search"

APIResourceSearch is the path to the API search resource.

View Source
const APIResourceSearchResultItem = "/api/search_result_item"

APIResourceSearchResultItem is the resource for accessing a SearchResultItem over HTTP API.

View Source
const DefaultScannerMaxOpenFiles = 250

DefaultScannerMaxOpenFiles is the maximum number of open files used by the Scanner by default.

View Source
const (
	EBookCategoryTypeAuthor = EBookCategoryTypeID(iota)
)
View Source
const ElasticAuthorFieldGutenbergID = "gutenberg_id"

ElasticAuthorFieldGutenbergID is the path to the GutenbergID field in the ElasticAuthor type.

View Source
const ElasticAuthorFieldID = "author_id"

ElasticAuthorFieldID is the path to the ID field in the ElasticAuthor type.

View Source
const ElasticAuthorFieldProperties = "properties"

ElasticAuthorFieldProperties is the path to the properties object in the ElasticAuthor type.

View Source
const ElasticEBookFieldID = "ebook_id"

ElasticEBookFieldID is the path to the ID field in the ElasticEBook type.

View Source
const ElasticEBookFieldProperties = "properties"

ElasticEBookFieldProperties is the path to the properties field in the ElasticEBook type.

View Source
const ElasticEBookFieldText = "book_text"

ElasticEBookFieldText is the path to the eBook text field in the ElasticEBook type.

View Source
const ElasticIndexAuthor = "gutenfinder_author"

ElasticIndexAuthor is the name of the ElasticAuthor index.

View Source
const ElasticIndexEBook = "gutenfinder_ebook"

ElasticIndexEBook is the name of the ElasticEBook index.

View Source
const ElasticPageSize = 100

ElasticPageSize sets the number of results retreived from elastic. This is set high temporarily, until we implement paging.

View Source
const ElasticTypeAuthor = "author"

ElasticTypeAuthor is the Elasticsearch type for ElasticAuthors.

View Source
const ElasticTypeEBook = "ebook"

ElasticTypeEBook is the Elasticsearch type for ElasticEBooks.

View Source
const FileExtensionRDF = ".rdf"

FileExtensionRDF is the extension of Project Gutenberg catalogue XML files.

View Source
const LandingResource = "/"

LandingResource is the resource path to the landing page.

View Source
const PropertyAuthorFullName = "name.full"
View Source
const PropertyEBookAgentID = PropertyKey("agent.id")
View Source
const PropertyEBookAgentName = PropertyKey("agent.name")

PropertyEBookAgentName is the property for an EBook's agent name

View Source
const PropertyEBookFile = PropertyKey("file")

PropertyEBookFile is the property for an EBook's files.

View Source
const PropertyEBookID = PropertyKey("parent.id")

PropertyEBookID is the property for an EBook's ID.

View Source
const PropertyEBookTitle = PropertyKey("title")

PropertyEBookTitle is the property for an EBook's title.

View Source
const SearchControllerTermParameter = "term"

SearchControllerTermParameter is the parameter to specify a search term.

View Source
const SearchResultItemIDParameter = "search_result_item_id"

SearchResultItemIDParameter is the name of the parameter for the SearchResultItem's ID.

View Source
const StaticFileDirectory = "static"

StaticFileDirectory is the path to the asset directory containing static files.

View Source
const WebsocketResourceSearch = "/websocket/search"

WebsocketResourceSearch is the path to the Websocket search resource.

View Source
const WebsocketResourceSearchResultItem = "/websocket/search_result_item"

WebsocketResourceSearchResultItem is the resource for accessing a SearchResultItem over a websocket.

Variables

View Source
var ElasticAuthorFieldAliases = ElasticPropertyField(PropertyAuthorFullName)

ElasticAuthorFieldAliases is the path to the author's name in the ElasticAuthor type.

Functions

func AllServices

func AllServices() []interface{}

func CanLog

func CanLog(level LogLevel) bool

CanLog returns true if messages at the given LogLevel would be logged.

func ElasticPropertyField

func ElasticPropertyField(property PropertyKey) string

ElasticPropertyField generates the path to field under "properties" in the Elastic ebook type.

func IsPermittedStaticFile

func IsPermittedStaticFile(filename string) bool

IsPermittedStaticFile returns false if the given filename is not in the whitelist. See PermittedStaticFiles().

func LogClose

func LogClose(closer io.Closer)

LogClose closes the closer, and logs an error if there is one.

func LogDebug

func LogDebug(msg string, args ...interface{})

LogDebug logs a debug message.

func LogErr

func LogErr(err error)

LogErr logs an error.

func LogError

func LogError(msg string, args ...interface{})

LogError logs an error message.

func LogFatal

func LogFatal(msg string, args ...interface{})

LogFatal logs an error message and panics.

func LogInfo

func LogInfo(msg string, args ...interface{})

LogInfo logs an info message.

func LogWarn

func LogWarn(msg string, args ...interface{})

LogWarn logs a warning message.

func OpenDatabaseConnection

func OpenDatabaseConnection(connectionString string) (*sqlx.DB, error)

OpenDatabaseConnection opens a connection to a postgres database.

func PermittedStaticFiles

func PermittedStaticFiles() []string

PermittedStaticFiles provides the paths of files which Gutenfinder is permitted to serve.

func RenderString

func RenderString(view View, viewName string, viewModel interface{}) (string, error)

RenderString renders the view as a String.

func SetLogLevel

func SetLogLevel(level LogLevel)

SetLogLevel sets the global log level for Gutenfinder.

func SetLogLevelByString

func SetLogLevelByString(level string) error

SetLogLevelByString sets the global log level for Gutenfinder.

func TemplateAssets

func TemplateAssets() []string

TemplateAssets returns the template paths within the asset bundle.

Types

type APIRouteController

type APIRouteController struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

APIRouteController handles protocol requests to the Gutenfinder API.

func (*APIRouteController) HandleRequest

func (controller *APIRouteController) HandleRequest(ctx context.Context, request *protocol.Request) *protocol.Response

HandleRequest dispatches the request to the appropriate RequestHandler.

func (*APIRouteController) SetRoutes

func (controller *APIRouteController) SetRoutes(routes ...APIRoutingOption)

SetRoutes defines the routes available to the APIController.

type APIRoutingOption

type APIRoutingOption func(controller *APIRouteController)

APIRoutingOption is used to set up an APIController.

func AddAPIRoute

func AddAPIRoute(resource string, handler RequestHandler) APIRoutingOption

AddAPIRoute is an APIRoutingOption that sets a route on the APIController.

type App

type App struct {
	Postgres       string
	ElasticOptions *ElasticOptions
	DB             SqlDB
	Elastic        *elastic.Client

	sync.Mutex
	// contains filtered or unexported fields
}

App initialises dependencies and runs functions in a context where those dependencies are active.

func (*App) LoadDependencies

func (app *App) LoadDependencies(components ...interface{}) error

LoadDependencies loads the dependencies for the given components. If Postgres and ElasticOptions are provided to the App, connections will be made to those services.

func (*App) LoadServices

func (app *App) LoadServices(components ...interface{}) error

func (*App) Run

func (app *App) Run(runner func() error) error

Run a function in the application context. If a database or elasticsearch connection is active, this connection will be closed when Run terminates.

type AssetBundle

type AssetBundle interface {
	Asset(name string) ([]byte, error)
}

AssetBundle represents a set of assets available to Gutenfinder.

type Author

type Author struct {
	Entity
	GutenbergID     string           `json:"gutenberg_id"`
	EBookCategory   *EBookCategory   `json:"category"`
	CatalogueUpdate *CatalogueUpdate `json:"-"`
	Properties      PropertyMap      `json:"properties,omitempty"`
}

Author represents a person who has written one or more EBooks. It is possible that an EBook has many authors.

func (*Author) AddEBooks

func (author *Author) AddEBooks(eBooks ...*EBook)

AddEBooks states that the author has written the given EBooks.

func (*Author) Aliases

func (author *Author) Aliases() []string

Aliases provides all names by which this author is known.

func (*Author) GetProperty

func (author *Author) GetProperty(property PropertyKey) (string, error)

GetProperty returns a property from the Author's property map, or an error if it is not available.

func (*Author) HasGutenbergID

func (author *Author) HasGutenbergID() bool

HasGutenbergID returns true if the Author's GutenbergID is not empty.

func (*Author) Identity

func (author *Author) Identity() string

Identity provides a summary of the Author's identity, whether or not it is persisted.

func (*Author) IsAttached

func (author *Author) IsAttached() bool

IsAttached returns true if the author has a CatalogueUpdate and EBookCategory attached.

func (*Author) IsCatalogueUpdateAttached

func (author *Author) IsCatalogueUpdateAttached() bool

IsCatalogueUpdateAttached returns true if the author has a CatalogueUpdate attached.

func (*Author) IsEBookCategoryAttached

func (author *Author) IsEBookCategoryAttached() bool

IsEBookCategoryAttached returns true if the author has a EBookCategory attached.

func (*Author) Merge

func (author *Author) Merge(other *Author)

Merge adds the other's properties and category to the receiver.

func (*Author) PrimaryAlias

func (author *Author) PrimaryAlias() (string, error)

PrimaryAlias provides the primary real name of the author. This is really a question for historians, but ultimately, we need to show a particular name on screen when someone looks up an author. If the author has no known aliases, an error is returned.

func (*Author) SetProperty

func (author *Author) SetProperty(property PropertyKey, value string)

SetProperty sets a property in the author's property map.

func (*Author) String

func (author *Author) String() string

type AuthorAliasFinderSource

type AuthorAliasFinderSource struct {
	ElasticAuthorRepository ElasticAuthorRepository
}

func (*AuthorAliasFinderSource) FindResultItems

func (source *AuthorAliasFinderSource) FindResultItems(ctx context.Context, search *Search) ([]*SearchResultItem, error)

type AuthorAliasSearchResultItem

type AuthorAliasSearchResultItem struct {
	Author *Author `json:"ebook"`
	Alias  string  `json:"alias"`
	// contains filtered or unexported fields
}

AuthorAliasSearchResultItem is a SearchResultItemType that references an Author's alias.

func (*AuthorAliasSearchResultItem) IsAttached

func (item *AuthorAliasSearchResultItem) IsAttached() bool

IsAttached returns true if the AuthorAliasSearchResultItem is attached to an Author.

func (*AuthorAliasSearchResultItem) String

func (item *AuthorAliasSearchResultItem) String() string

type AuthorAliasSearchResultItemRepository

type AuthorAliasSearchResultItemRepository interface {
	// Get retrieves a AuthorAliasSearchResultItem by ID.  An error will be returned if a AuthorAliasSearchResultItem cannot be found.
	Get(ctx context.Context, tx Tx, id int64) (*AuthorAliasSearchResultItem, error)
	// Save will insert or update the given AuthorAliasSearchResultItems as appropriate.
	Save(ctx context.Context, tx Tx, aliasSearchResultItem ...*AuthorAliasSearchResultItem) error
}

type AuthorAliasSearchResultItemRepositoryImpl

type AuthorAliasSearchResultItemRepositoryImpl struct {
	Repository `inject:"inline"`
}

AuthorAliasSearchResultItemRepositoryImpl is the database interface for AuthorAliasSearchResultItems.

func (AuthorAliasSearchResultItemRepositoryImpl) Get

Get retrieves a AuthorAliasSearchResultItem by ID. An error will be returned if a AuthorAliasSearchResultItem cannot be found.

func (AuthorAliasSearchResultItemRepositoryImpl) Save

func (repo AuthorAliasSearchResultItemRepositoryImpl) Save(ctx context.Context, tx Tx, aliasSearchResultItem ...*AuthorAliasSearchResultItem) error

Save will insert or update the given AuthorAliasSearchResultItems as appropriate.

type AuthorIndexer

type AuthorIndexer interface {
	// IndexNewAuthorUpdates finds CatalogueUpdates that have not been indexed, and indexes all associated authors on Elasticsearch.
	IndexNewAuthorUpdates(ctx context.Context) error
}

type AuthorIndexerImpl

type AuthorIndexerImpl struct {
	DB                        SqlDB                     `inject:""`
	ElasticAuthorRepository   ElasticAuthorRepository   `inject:""`
	CatalogueUpdateRepository CatalogueUpdateRepository `inject:""`
}

AuthorIndexerImpl indexes authors on Elasticsearch.

func (AuthorIndexerImpl) IndexNewAuthorUpdates

func (indexer AuthorIndexerImpl) IndexNewAuthorUpdates(ctx context.Context) error

IndexNewAuthorUpdates finds CatalogueUpdates that have not been indexed, and indexes all associated authors on Elasticsearch.

type AuthorMatcher

type AuthorMatcher interface {
	// MatchMissingEBooks matches new EBooks to authors.  If no author exists for an EBook, create it.
	MatchMissingEBooks(ctx context.Context) error
}

type AuthorMatcherImpl

type AuthorMatcherImpl struct {
	DB                        SqlDB                         `inject:""`
	CatalogueUpdateRepository CatalogueUpdateRepositoryImpl `inject:"inline"`
	EBookRepository           EBookRepositoryImpl           `inject:"inline"`
	AuthorRepository          AuthorRepositoryImpl          `inject:"inline"`
}

AuthorMatcherImpl matches EBooks to authors.

func (AuthorMatcherImpl) MatchMissingEBooks

func (matcher AuthorMatcherImpl) MatchMissingEBooks(ctx context.Context) error

MatchMissingEBooks matches new EBooks to authors. If no author exists for an EBook, create it.

type AuthorRepository

type AuthorRepository interface {
	// FindForEBooks finds the authors associated with the EBooks.  If no author is recorded for the ebooks, nil is returned.
	FindForEBooks(ctx context.Context, tx Tx, eBooks ...*EBook) ([]*Author, error)
	// AppendByGutenbergID adds data to the authors, and ensures any associated EBooks are linked.
	AppendByGutenbergID(ctx context.Context, tx Tx, authors ...*Author) error
	// FindByGutenbergID finds the author with the given GutenbergID.  If no such author is found, an error is returned.
	FindByGutenbergID(ctx context.Context, tx Tx, gutenbergID string) (*Author, error)
	// Get finds an Author with the given ID.  If no such Author is found, an error is returned.
	Get(ctx context.Context, tx Tx, id int64) (*Author, error)
	// List returns all Authors saved in the database, in no particular order.
	List(ctx context.Context, tx Tx) ([]*Author, error)
	// Save persists Authors in the database.  If an author is already persisted, it will be updated.
	Save(ctx context.Context, tx Tx, authors ...*Author) error
}

type AuthorRepositoryImpl

type AuthorRepositoryImpl struct {
	Repository              `inject:"inline"`
	EBookRepository         EBookRepositoryImpl         `inject:"inline"`
	EBookCategoryRepository EBookCategoryRepositoryImpl `inject:"inline"`
}

AuthorRepositoryImpl is a database interface for Authors.

func (AuthorRepositoryImpl) AppendByGutenbergID

func (repo AuthorRepositoryImpl) AppendByGutenbergID(ctx context.Context, tx Tx, authors ...*Author) error

AppendByGutenbergID adds data to the authors, and ensures any associated EBooks are linked.

func (AuthorRepositoryImpl) FindByGutenbergID

func (repo AuthorRepositoryImpl) FindByGutenbergID(ctx context.Context, tx Tx, gutenbergID string) (*Author, error)

FindByGutenbergID finds the author with the given GutenbergID. If no such author is found, an error is returned.

func (AuthorRepositoryImpl) FindForEBooks

func (repo AuthorRepositoryImpl) FindForEBooks(ctx context.Context, tx Tx, eBooks ...*EBook) ([]*Author, error)

FindForEBooks finds the authors associated with the EBooks. If no author is recorded for the ebooks, nil is returned.

func (AuthorRepositoryImpl) Get

func (repo AuthorRepositoryImpl) Get(ctx context.Context, tx Tx, id int64) (*Author, error)

Get finds an Author with the given ID. If no such Author is found, an error is returned.

func (AuthorRepositoryImpl) List

func (repo AuthorRepositoryImpl) List(ctx context.Context, tx Tx) ([]*Author, error)

List returns all Authors saved in the database, in no particular order.

func (AuthorRepositoryImpl) Save

func (repo AuthorRepositoryImpl) Save(ctx context.Context, tx Tx, authors ...*Author) error

Save persists Authors in the database. If an author is already persisted, it will be updated.

type BindataAssetBundle

type BindataAssetBundle struct{}

BindataAssetBundle is an AssetBundle provided by Bindata.

func (BindataAssetBundle) Asset

func (BindataAssetBundle) Asset(name string) ([]byte, error)

Asset provides a Bindata Asset.

type BindataDir

type BindataDir struct {
	Dir         string
	AssetBundle AssetBundle

	sync.RWMutex
	// contains filtered or unexported fields
}

BindataDir is a HTTP filesystem using a directory within Bindata assets.

func (*BindataDir) Open

func (dir *BindataDir) Open(name string) (http.File, error)

Open returns a Bindata asset wrapped up as a http.File.

type CatalogueUpdate

type CatalogueUpdate struct {
	Entity
	Type       CatalogueUpdateTypeID
	CreateTime time.Time `json:"create_time"`
	// IsIndexed should be set to true when the items associated with this CatalogueUpdate have all been indexed on Elasticsearch.
	IsIndexed bool      `json:"is_indexed"`
	EBooks    []*EBook  `json:"ebooks,omitempty"`
	Authors   []*Author `json:"authors,omitempty"`
}

CatalogueUpdate represents a point in time where EBooks were added into Gutenfinder.

func (*CatalogueUpdate) String

func (catalogueUpdate *CatalogueUpdate) String() string

func (*CatalogueUpdate) UpdateChildOwner

func (catalogueUpdate *CatalogueUpdate) UpdateChildOwner()

UpdateChildOwner sets the CatalogueUpdate attached to child entities.

type CatalogueUpdateRepository

type CatalogueUpdateRepository interface {
	// Save will create or update the given CatalogueUpdates as appropriate.
	Save(ctx context.Context, tx Tx, catalogueUpdates ...*CatalogueUpdate) error
	// Get retrieves the CatalogueUpdate with the given ID.  An error is returned if no such CatalogueUpdate can be found.
	Get(ctx context.Context, tx Tx, id int64) (*CatalogueUpdate, error)
	// List returns all CatalogueUpdates.
	List(ctx context.Context, tx Tx) ([]*CatalogueUpdate, error)
	// FindByType returns all CatalogueUpdates of the given type.
	FindByType(ctx context.Context, tx Tx, typeID CatalogueUpdateTypeID) ([]*CatalogueUpdate, error)
	// FindByIndexStatus finds all CatalogueUpdates with an IsIndexed equal to the isIndexed parameter.
	FindByIndexStatus(ctx context.Context, tx Tx, typeID CatalogueUpdateTypeID, isIndexed bool) ([]*CatalogueUpdate, error)
	// FindMostRecent retreives the most recent CatalogueUpdate.
	FindMostRecent(ctx context.Context, tx Tx) (*CatalogueUpdate, error)
	// CreateFromEBookChannel creates a new CatalogueUpdate and populates the EBook repository with EBooks linked to that CatalogueUpdate.  If no EBooks are provided in the channel, the CatalogueUpdate will not be persisted.
	CreateFromEBookChannel(ctx context.Context, tx Tx, eBooks <-chan *EBook) (*CatalogueUpdate, error)
}

type CatalogueUpdateRepositoryImpl

type CatalogueUpdateRepositoryImpl struct {
	Repository          `inject:"inline"`
	EBookRepository     EBookRepositoryImpl     `inject:"inline"`
	EBookFileRepository EBookFileRepositoryImpl `inject:"inline"`
}

CatalogueUpdateRepositoryImpl is a database interface for CatalogueUpdates.

func (CatalogueUpdateRepositoryImpl) CreateFromEBookChannel

func (repo CatalogueUpdateRepositoryImpl) CreateFromEBookChannel(ctx context.Context, tx Tx, eBooks <-chan *EBook) (*CatalogueUpdate, error)

CreateFromEBookChannel creates a new CatalogueUpdate and populates the EBook repository with EBooks linked to that CatalogueUpdate. If no EBooks are provided in the channel, the CatalogueUpdate will not be persisted.

func (CatalogueUpdateRepositoryImpl) FindByIndexStatus

func (repo CatalogueUpdateRepositoryImpl) FindByIndexStatus(ctx context.Context, tx Tx, typeID CatalogueUpdateTypeID, isIndexed bool) ([]*CatalogueUpdate, error)

FindByIndexStatus finds all CatalogueUpdates with an IsIndexed equal to the isIndexed parameter.

func (CatalogueUpdateRepositoryImpl) FindByType

FindByType returns all CatalogueUpdates of the given type.

func (CatalogueUpdateRepositoryImpl) FindMostRecent

func (repo CatalogueUpdateRepositoryImpl) FindMostRecent(ctx context.Context, tx Tx) (*CatalogueUpdate, error)

FindMostRecent retreives the most recent CatalogueUpdate.

func (CatalogueUpdateRepositoryImpl) Get

Get retrieves the CatalogueUpdate with the given ID. An error is returned if no such CatalogueUpdate can be found.

func (CatalogueUpdateRepositoryImpl) List

List returns all CatalogueUpdates.

func (CatalogueUpdateRepositoryImpl) Save

func (repo CatalogueUpdateRepositoryImpl) Save(ctx context.Context, tx Tx, catalogueUpdates ...*CatalogueUpdate) error

Save will create or update the given CatalogueUpdates as appropriate.

type CatalogueUpdateTypeID

type CatalogueUpdateTypeID int64

type DependencyInjector

type DependencyInjector interface {
	InjectDependencies(components ...interface{}) error
}

DependencyInjector represents a type that can inject dependencies for components.

type EBook

type EBook struct {
	Entity
	CatalogueUpdate *CatalogueUpdate `json:"-"`
	GutenbergID     string           `json:"gutenberg_id"`
	Properties      PropertyMap      `json:"properties"`
	Files           []*EBookFile     `json:"files"`
}

EBook represents a book in our collection. Their source is a Project Gutenberg mirror.

func FilterIndexableEBooks

func FilterIndexableEBooks(eBooks []*EBook) []*EBook

FilterIndexableEBooks returns those eBooks passed that have an Index file.

func ParseEBook

func ParseEBook(reader io.Reader) (*EBook, error)

ParseEBook reads an EBook from a reader that contains a Project Gutenberg RDF catalogue file.

func (*EBook) AddAuthorProperties

func (eBook *EBook) AddAuthorProperties(authorProperties map[PropertyKey]string) error

AddAuthorProperties adds a hint about an EBook author's identity.

func (*EBook) AddFiles

func (eBook *EBook) AddFiles(files ...*EBookFile)

AddFiles adds files to the EBook. If no index file is set, it will set the index on the first local file.

func (*EBook) AttachLocalFiles

func (eBook *EBook) AttachLocalFiles(root string) error

AttachLocalFiles finds the local files for this EBook and attaches them.

func (*EBook) AuthorProfiles

func (eBook *EBook) AuthorProfiles() ([]*Author, error)

AuthorProfiles provides a hint to the EBook authors identites, based on the EBook properties. If insufficient data is available, an error is returned.

func (*EBook) FindIndexFile

func (eBook *EBook) FindIndexFile() *EBookFile

FindIndexFile returns the index file, if available.

func (*EBook) GetGutenbergNumber

func (eBook *EBook) GetGutenbergNumber() (string, error)

GetGutenbergNumber returns the numeric GutenbergId as a string.

func (*EBook) GetIndexFilePath

func (eBook *EBook) GetIndexFilePath() (EncodedFilePath, error)

GetIndexFilePath returns the file path for the index file.

func (*EBook) GetProperty

func (eBook *EBook) GetProperty(property PropertyKey) (string, error)

GetProperty returns a property from the EBook's property map, or an error if there is no such property.

func (*EBook) HasIndexFile

func (eBook *EBook) HasIndexFile() bool

HasIndexFile returns true if the EBook has an index file.

func (*EBook) Identity

func (eBook *EBook) Identity() string

Identity provides an summary of the EBook's identity, whether or not it is persisted.

func (*EBook) IsAttached

func (eBook *EBook) IsAttached() bool

IsAttached returns true if the EBook is attached to its parent structure.

func (*EBook) LoadTextFilePaths

func (eBook *EBook) LoadTextFilePaths(root string) ([]EncodedFilePath, error)

LoadTextFilePaths finds all local files for this EBook.

func (*EBook) SetProperty

func (eBook *EBook) SetProperty(property PropertyKey, value string)

SetProperty sets a property in the EBook's property map.

func (*EBook) String

func (eBook *EBook) String() string

func (*EBook) Title

func (eBook *EBook) Title() string

Title returns the title of the EBook, if present in the Properties.

func (*EBook) UpdateFilesOwner

func (eBook *EBook) UpdateFilesOwner()

UpdateFilesOwner ensures all EBookFiles reference the EBook.

type EBookCategory

type EBookCategory struct {
	Entity
	Members []*EBookCategoryMember `json:"members"`
	Type    EBookCategoryTypeID    `json:"type"`
}

EBookCategory represents a category of EBooks. EBookCategory membership is many-to-many.

func (*EBookCategory) AddEBooks

func (category *EBookCategory) AddEBooks(eBooks ...*EBook)

AddEBooks associates the given EBooks with the category.

func (*EBookCategory) AddMembers

func (category *EBookCategory) AddMembers(members ...*EBookCategoryMember)

TODO write unit test for AddMembers

func (*EBookCategory) GetEBooks

func (category *EBookCategory) GetEBooks() []*EBook

GetEBooks gets all EBooks recorded against this category.

func (*EBookCategory) Merge

func (category *EBookCategory) Merge(other *EBookCategory)

Merge creates a category that is a union of the members. If a member is persisted in both categories, that member in other overrides the member in category.

func (*EBookCategory) String

func (category *EBookCategory) String() string

func (*EBookCategory) UpdateMembersOwner

func (category *EBookCategory) UpdateMembersOwner()

UpdateMembersOwner assigns the category ID to all members within the category structure.

type EBookCategoryMember

type EBookCategoryMember struct {
	Entity
	EBookCategory *EBookCategory `json:"-"`
	EBook         *EBook         `json:"ebook"`
}

type EBookCategoryMemberRepository

type EBookCategoryMemberRepository interface {
	Get(ctx context.Context, tx Tx, id int64) (*EBookCategoryMember, error)
	ListForEBookCategory(ctx context.Context, tx Tx, category *EBookCategory) ([]*EBookCategoryMember, error)
	// Save persists EBookCategoryMembers in the database.  The linked EBook should already be persisted; it will not be saved.
	Save(ctx context.Context, tx Tx, members ...*EBookCategoryMember) error
}

type EBookCategoryMemberRepositoryImpl

type EBookCategoryMemberRepositoryImpl struct {
	Repository      `inject:"inline"`
	EBookRepository EBookRepositoryImpl `inject:"inline"`
}

func (EBookCategoryMemberRepositoryImpl) Get

func (EBookCategoryMemberRepositoryImpl) ListForEBookCategory

func (repo EBookCategoryMemberRepositoryImpl) ListForEBookCategory(ctx context.Context, tx Tx, category *EBookCategory) ([]*EBookCategoryMember, error)

func (EBookCategoryMemberRepositoryImpl) Save

Save persists EBookCategoryMembers in the database. The linked EBook should already be persisted; it will not be saved.

type EBookCategoryRepository

type EBookCategoryRepository interface {
	// FindForEBooks finds the EBookCategories associated with the EBooks.  If no EBookcategory is recorded for the ebooks, nil is returned.
	FindForEBooks(ctx context.Context, tx Tx, eBooks ...*EBook) ([]*EBookCategory, error)
	// Get finds an EBookCategory with the given ID.  If no such EBookCategory is found, an error will be returned.
	Get(ctx context.Context, tx Tx, id int64) (*EBookCategory, error)
	// Save persists EBookCategories in the database.  Linked EBooks must already be persisted: they will not be saved.
	Save(ctx context.Context, tx Tx, categories ...*EBookCategory) error
}

type EBookCategoryRepositoryImpl

type EBookCategoryRepositoryImpl struct {
	Repository                        `inject:"inline"`
	EBookCategoryMemberRepositoryImpl `inject:"inline"`
}

func (EBookCategoryRepositoryImpl) FindForEBooks

func (repo EBookCategoryRepositoryImpl) FindForEBooks(ctx context.Context, tx Tx, eBooks ...*EBook) ([]*EBookCategory, error)

FindForEBooks finds the EBookCategories associated with the EBooks. If no EBookcategory is recorded for the ebooks, nil is returned.

func (EBookCategoryRepositoryImpl) Get

Get finds an EBookCategory with the given ID. If no such EBookCategory is found, an error will be returned.

func (EBookCategoryRepositoryImpl) Save

func (repo EBookCategoryRepositoryImpl) Save(ctx context.Context, tx Tx, categories ...*EBookCategory) error

Save persists EBookCategories in the database. Linked EBooks must already be persisted: they will not be saved.

type EBookCategoryTypeID

type EBookCategoryTypeID int64

EBookCategoryTypeID represents the type of an EBookCategory.

func (EBookCategoryTypeID) String

func (typeID EBookCategoryTypeID) String() string

type EBookFile

type EBookFile struct {
	Entity
	// TODO impement custom marshaler to print ebook id or other information.
	EBook    *EBook         `json:"-"`
	URL      string         `json:"url"`
	IsIndex  bool           `json:"is_index"`
	Encoding TextEncodingID `json:"encoding_id"`
}

EBookFile is a file attached to an EBook.

func MakeEBookFileFromPath

func MakeEBookFileFromPath(path EncodedFilePath) *EBookFile

MakeEBookFileFromPath creates an EBookFile given a path.

func MakeEBookFilesFromPaths

func MakeEBookFilesFromPaths(paths ...EncodedFilePath) []*EBookFile

MakeEBookFilesFromPaths creates one EBookFile per input path.

func (*EBookFile) IsAttached

func (file *EBookFile) IsAttached() bool

IsAttached returns true if the EBookFile is linked to its parent structure.

func (*EBookFile) IsLocal

func (file *EBookFile) IsLocal() bool

IsLocal returns true if the EBook has a "file://" URL.

func (*EBookFile) MakeFilePath

func (file *EBookFile) MakeFilePath() (EncodedFilePath, error)

MakeFilePath returns a filepath for the EBookFile.

func (*EBookFile) String

func (file *EBookFile) String() string

type EBookFileRepository

type EBookFileRepository interface {
	// LoadFilesForEBooks loads all files for all the given EBooks and adds them to the entities.
	LoadFilesForEBooks(ctx context.Context, tx Tx, eBooks ...*EBook) error
	// Get retrieves an EBookFile by Id.  The associated EBook will be retrieved but will not include any files.
	Get(ctx context.Context, tx Tx, id int64) (*EBookFile, error)
	// ListForEBook finds all EBookFiles that reference the given EBook.
	ListForEBook(ctx context.Context, tx Tx, eBook *EBook) ([]*EBookFile, error)
	// Save will insert or update EBookFiles as appropriate.
	Save(ctx context.Context, tx Tx, eBookFile ...*EBookFile) error
}

type EBookFileRepositoryImpl

type EBookFileRepositoryImpl struct {
	Repository `inject:"inline"`
}

EBookFileRepositoryImpl is the database interface for EBookFile.

func (EBookFileRepositoryImpl) Get

func (repo EBookFileRepositoryImpl) Get(ctx context.Context, tx Tx, id int64) (*EBookFile, error)

Get retrieves an EBookFile by Id. The associated EBook will be retrieved but will not include any files.

func (EBookFileRepositoryImpl) ListForEBook

func (repo EBookFileRepositoryImpl) ListForEBook(ctx context.Context, tx Tx, eBook *EBook) ([]*EBookFile, error)

ListForEBook finds all EBookFiles that reference the given EBook.

func (EBookFileRepositoryImpl) LoadFilesForEBooks

func (repo EBookFileRepositoryImpl) LoadFilesForEBooks(ctx context.Context, tx Tx, eBooks ...*EBook) error

LoadFilesForEBooks loads all files for all the given EBooks and adds them to the entities.

func (EBookFileRepositoryImpl) Save

func (repo EBookFileRepositoryImpl) Save(ctx context.Context, tx Tx, eBookFile ...*EBookFile) error

Save will insert or update EBookFiles as appropriate.

type EBookHighlight

type EBookHighlight struct {
	TextHighlight []string `json:"book_text,omitempty"`
}

EBookHighlight provides a snippet in elastic search results.

type EBookIndexer

type EBookIndexer interface {
	// IndexEBookUpdates indexes all CatalogueUpdates and so can be used to recover when an Elasticsearch index is deleted.
	IndexEBookUpdates(ctx context.Context) error
	// IndexNewEBookUpdates finds CatalogueUpdates that have not been indexed, and indexes all associated EBooks on Elasticsearch.
	IndexNewEBookUpdates(ctx context.Context) error
}

type EBookIndexerImpl

type EBookIndexerImpl struct {
	DB                        SqlDB                         `inject:""`
	ElasticEBookRepository    ElasticEBookRepositoryImpl    `inject:"inline"`
	CatalogueUpdateRepository CatalogueUpdateRepositoryImpl `inject:"inline"`
	Scanner                   *ScannerImpl                  `inject:""`
}

EBookIndexerImpl discovers new EBooks and indexes them on Elasticsearch.

func (EBookIndexerImpl) IndexEBookUpdates

func (indexer EBookIndexerImpl) IndexEBookUpdates(ctx context.Context) error

IndexAllCatalogueUpdates indexes all CatalogueUpdates and so can be used to recover when an Elasticsearch index is deleted.

func (EBookIndexerImpl) IndexNewEBookUpdates

func (indexer EBookIndexerImpl) IndexNewEBookUpdates(ctx context.Context) error

IndexNewEBookUpdates finds CatalogueUpdates that have not been indexed, and indexes all associated EBooks on Elasticsearch.

type EBookParser

type EBookParser struct {
	// contains filtered or unexported fields
}

func (*EBookParser) Parse

func (parser *EBookParser) Parse(reader io.Reader) (*EBook, error)

ParseEBook reads an EBook from a reader that contains a Project Gutenberg RDF catalogue file.

type EBookRepository

type EBookRepository interface {
	// SaveIfNewGutenbergID saves EBooks if their Gutenberg ID is new.
	SaveIfNewGutenbergID(ctx context.Context, tx Tx, eBooks ...*EBook) error
	// FindByGutenbergID retrieves the EBook matching the given GutenbergID.
	FindByGutenbergID(ctx context.Context, tx Tx, gutenbergID string) (*EBook, error)
	// Get retrieves an EBook from the database by its ID.
	Get(ctx context.Context, tx Tx, id int64) (*EBook, error)
	// FindAuthorless finds all EBooks with an Author profile that is not linked to a persisted Author.
	FindAuthorless(ctx context.Context, tx Tx) ([]*EBook, error)
	// FindAll retrieves a slice of EBooks from the database, each matching a given id.
	FindAll(ctx context.Context, tx Tx, id int64, ids ...int64) ([]*EBook, error)
	// List finds all EBooks in the database.
	List(ctx context.Context, tx Tx) ([]*EBook, error)
	// FindForCatalogueUpdate finds all EBooks that are associated with the given CatalogueUpdate.
	FindForCatalogueUpdate(ctx context.Context, tx Tx, catalogueUpdate *CatalogueUpdate) ([]*EBook, error)
	// Save inserts or updates the given EBooks as appropriate.
	Save(ctx context.Context, tx Tx, eBook ...*EBook) error
	FindForCategory(ctx context.Context, tx Tx, category *EBookCategory) ([]*EBook, error)
}

type EBookRepositoryImpl

type EBookRepositoryImpl struct {
	Repository `inject:"inline"`
	FileRepo   EBookFileRepositoryImpl `inject:"inline"`
}

EBookRepositoryImpl is a database interface for EBooks.

func (EBookRepositoryImpl) FindAll

func (repo EBookRepositoryImpl) FindAll(ctx context.Context, tx Tx, id int64, ids ...int64) ([]*EBook, error)

FindAll retrieves a slice of EBooks from the database, each matching a given id.

func (EBookRepositoryImpl) FindAuthorless

func (repo EBookRepositoryImpl) FindAuthorless(ctx context.Context, tx Tx) ([]*EBook, error)

FindAuthorless finds all EBooks with an Author profile that is not linked to a persisted Author.

func (EBookRepositoryImpl) FindByGutenbergID

func (repo EBookRepositoryImpl) FindByGutenbergID(ctx context.Context, tx Tx, gutenbergID string) (*EBook, error)

FindByGutenbergID retrieves the EBook matching the given GutenbergID.

func (EBookRepositoryImpl) FindForCatalogueUpdate

func (repo EBookRepositoryImpl) FindForCatalogueUpdate(ctx context.Context, tx Tx, catalogueUpdate *CatalogueUpdate) ([]*EBook, error)

FindForCatalogueUpdate finds all EBooks that are associated with the given CatalogueUpdate.

func (EBookRepositoryImpl) FindForCategory

func (repo EBookRepositoryImpl) FindForCategory(ctx context.Context, tx Tx, category *EBookCategory) ([]*EBook, error)

func (EBookRepositoryImpl) Get

func (repo EBookRepositoryImpl) Get(ctx context.Context, tx Tx, id int64) (*EBook, error)

Get retrieves an EBook from the database by its ID.

func (EBookRepositoryImpl) List

func (repo EBookRepositoryImpl) List(ctx context.Context, tx Tx) ([]*EBook, error)

List finds all EBooks in the database.

func (EBookRepositoryImpl) Save

func (repo EBookRepositoryImpl) Save(ctx context.Context, tx Tx, eBook ...*EBook) error

Save inserts or updates the given EBooks as appropriate.

func (EBookRepositoryImpl) SaveIfNewGutenbergID

func (repo EBookRepositoryImpl) SaveIfNewGutenbergID(ctx context.Context, tx Tx, eBooks ...*EBook) error

SaveIfNewGutenbergID saves EBooks if their Gutenberg ID is new.

type EBookTextFinderSource

type EBookTextFinderSource struct {
	ElasticEBookRepository ElasticEBookRepository
}

func (*EBookTextFinderSource) FindResultItems

func (source *EBookTextFinderSource) FindResultItems(ctx context.Context, search *Search) ([]*SearchResultItem, error)

type EBookTextLoader

type EBookTextLoader struct {
	EBook   *EBook
	Timeout time.Duration
}

EBookTextLoader loads the text for EBooks.

func (EBookTextLoader) ReadIndexFile

func (loader EBookTextLoader) ReadIndexFile(ctx context.Context) ([]byte, error)

ReadIndexFile reads the entire Index file and returns the data as a byte slice.

func (EBookTextLoader) ReadIndexFileParagraphs

func (loader EBookTextLoader) ReadIndexFileParagraphs(ctx context.Context) ([]string, error)

ReadIndexFileParagraphs reads the index file, splitting on paragraphs.

type EBookTitleFinderSource

type EBookTitleFinderSource struct {
	ElasticEBookRepository ElasticEBookRepository
}

func (*EBookTitleFinderSource) FindResultItems

func (source *EBookTitleFinderSource) FindResultItems(ctx context.Context, search *Search) ([]*SearchResultItem, error)

type ElasticAuthor

type ElasticAuthor struct {
	AuthorID          int64       `json:"author_id"`
	AuthorGutenbergID string      `json:"gutenberg_id"`
	Properties        PropertyMap `json:"properties"`
}

ElasticAuthor is the representation of an author handled by Elasticsearch.

func MakeElasticAuthor

func MakeElasticAuthor(author *Author) *ElasticAuthor

MakeElasticAuthor creates the representation of an Author saved on ElasticSearch.

func (*ElasticAuthor) GetAuthor

func (elasticAuthor *ElasticAuthor) GetAuthor() (*Author, error)

GetAuthor provides the database Entity representation of the Elasticsearch Entity.

func (*ElasticAuthor) GetAuthorIDAsString

func (elasticAuthor *ElasticAuthor) GetAuthorIDAsString() string

GetAuthorIDAsString provides the Author's ID as a string.

func (*ElasticAuthor) String

func (elasticAuthor *ElasticAuthor) String() string

type ElasticAuthorRepository

type ElasticAuthorRepository interface {
	// Index the given ElasticAuthors.
	Index(ctx context.Context, authors ...*ElasticAuthor) error
	// SearchAliases finds authors by their aliases.
	SearchAliases(ctx context.Context, term string) ([]*SearchResultItem, error)
	// Search authors by the given term and field.  The includeFields will be returned in the results.
	Search(ctx context.Context, term, field string, includeFields ...string) ([]*ElasticAuthor, error)
	// RunQuery executes an Elasticsearch query against the EBook type.
	RunQuery(ctx context.Context, query elastic.Query, builderFunc ...SearchOptionFunc) ([]*ElasticAuthor, error)
	// Mapping is the ElasticSearch mapping for Authors.
	Mapping() ElasticIndexDefinition
}

type ElasticAuthorRepositoryImpl

type ElasticAuthorRepositoryImpl struct {
	ElasticRepository `inject:"inline"`
	ElasticWorkers
}

ElasticAuthorRepositoryImpl is the Elasticsearch interface for Authors.

func (ElasticAuthorRepositoryImpl) Index

func (repo ElasticAuthorRepositoryImpl) Index(ctx context.Context, authors ...*ElasticAuthor) error

Index the given ElasticAuthors.

func (ElasticAuthorRepositoryImpl) Mapping

Mapping is the ElasticSearch mapping for Authors.

func (ElasticAuthorRepositoryImpl) RunQuery

func (repo ElasticAuthorRepositoryImpl) RunQuery(ctx context.Context, query elastic.Query, builderFunc ...SearchOptionFunc) ([]*ElasticAuthor, error)

RunQuery executes an Elasticsearch query against the EBook type.

func (ElasticAuthorRepositoryImpl) Search

func (repo ElasticAuthorRepositoryImpl) Search(ctx context.Context, term, field string, includeFields ...string) ([]*ElasticAuthor, error)

Search authors by the given term and field. The includeFields will be returned in the results.

func (ElasticAuthorRepositoryImpl) SearchAliases

func (repo ElasticAuthorRepositoryImpl) SearchAliases(ctx context.Context, term string) ([]*SearchResultItem, error)

SearchAliases finds authors by their aliases.

type ElasticEBook

type ElasticEBook struct {
	EBookID    int64          `json:"ebook_id"`
	Properties PropertyMap    `json:"properties,omitempty"`
	Text       string         `json:"book_text,omitempty"`
	Highlight  EBookHighlight `json:"highlight,omitempty"`
}

ElasticEBook is the representation of an EBook handled by Elasticsearch.

func MakeElasticEBook

func MakeElasticEBook(eBook *EBook, text string) *ElasticEBook

MakeElasticEBook builds the Elasticsearch representation of an EBook.

func (*ElasticEBook) EBookIDString

func (elasticEBook *ElasticEBook) EBookIDString() string

EBookIDString returns the EBook ID as a string.

func (*ElasticEBook) GetEBook

func (elasticEBook *ElasticEBook) GetEBook() (*EBook, error)

GetEBook gets the EBook referenced by the ElasticEBook. (It does not hit the database.)

func (*ElasticEBook) String

func (elasticEBook *ElasticEBook) String() string

type ElasticEBookRepository

type ElasticEBookRepository interface {
	// SearchTitle searches for EBook titles matching the given term.
	SearchTitle(ctx context.Context, term string) ([]*SearchResultItem, error)
	// SearchText searched for EBook texts matching the given term.
	SearchText(ctx context.Context, term string) ([]*SearchResultItem, error)
	// Search finds EBooks in elastic.
	Search(ctx context.Context, term, field string, includeFields ...string) ([]*ElasticEBook, error)
	// SearchWithHighlight searches the EBook type and returns snippets attached to the results.
	SearchWithHighlight(ctx context.Context, term, field string, includeFields ...string) ([]*ElasticEBook, error)
	// RunQuery executes an Elasticsearch query against the EBook type.
	RunQuery(ctx context.Context, query elastic.Query, builderFunc ...SearchOptionFunc) ([]*ElasticEBook, error)
	// IndexWithProcessor indexes EBooks with a long running processor.
	IndexWithProcessor(ctx context.Context, eBookChan <-chan *ElasticEBook) error
	// Index indexes the given EBooks on Elasticsearch.
	Index(ctx context.Context, eBooks ...*ElasticEBook) error
	Mapping() ElasticIndexDefinition
}

type ElasticEBookRepositoryImpl

type ElasticEBookRepositoryImpl struct {
	ElasticRepository `inject:"inline"`
	ElasticWorkers
}

ElasticEBookRepositoryImpl is an Elasticsearch interface for EBooks.

func (ElasticEBookRepositoryImpl) Index

func (repo ElasticEBookRepositoryImpl) Index(ctx context.Context, eBooks ...*ElasticEBook) error

Index indexes the given EBooks on Elasticsearch.

func (ElasticEBookRepositoryImpl) IndexWithProcessor

func (repo ElasticEBookRepositoryImpl) IndexWithProcessor(ctx context.Context, eBookChan <-chan *ElasticEBook) error

IndexWithProcessor indexes EBooks with a long running processor.

func (ElasticEBookRepositoryImpl) Mapping

func (ElasticEBookRepositoryImpl) RunQuery

func (repo ElasticEBookRepositoryImpl) RunQuery(ctx context.Context, query elastic.Query, builderFunc ...SearchOptionFunc) ([]*ElasticEBook, error)

RunQuery executes an Elasticsearch query against the EBook type.

func (ElasticEBookRepositoryImpl) Search

func (repo ElasticEBookRepositoryImpl) Search(ctx context.Context, term, field string, includeFields ...string) ([]*ElasticEBook, error)

Search finds EBooks in elastic.

func (ElasticEBookRepositoryImpl) SearchText

func (repo ElasticEBookRepositoryImpl) SearchText(ctx context.Context, term string) ([]*SearchResultItem, error)

SearchText searched for EBook texts matching the given term.

func (ElasticEBookRepositoryImpl) SearchTitle

func (repo ElasticEBookRepositoryImpl) SearchTitle(ctx context.Context, term string) ([]*SearchResultItem, error)

SearchTitle searches for EBook titles matching the given term.

func (ElasticEBookRepositoryImpl) SearchWithHighlight

func (repo ElasticEBookRepositoryImpl) SearchWithHighlight(ctx context.Context, term, field string, includeFields ...string) ([]*ElasticEBook, error)

SearchWithHighlight searches the EBook type and returns snippets attached to the results.

type ElasticFieldDefinition

type ElasticFieldDefinition map[string]string

type ElasticIndexDefinition

type ElasticIndexDefinition struct {
	Settings map[string]int                      `json:"settings"`
	Mappings map[string]ElasticMappingDefinition `json:"mappings"`
}

type ElasticMappingDefinition

type ElasticMappingDefinition struct {
	Properties map[string]ElasticFieldDefinition `json:"properties"`
}

type ElasticOptions

type ElasticOptions struct {
	Options []elastic.ClientOptionFunc
}

ElasticOptions are connection options for Elasticsearch.

func MakeElasticOptionsForURL

func MakeElasticOptionsForURL(elasticURL string) *ElasticOptions

MakeElasticOptionsForURL creates an ElasticOptions that will use the given URL.

func (*ElasticOptions) Connect

func (options *ElasticOptions) Connect() (*elastic.Client, error)

Connect opens a connection to Elasticsearch.

type ElasticRepository

type ElasticRepository struct {
	Elastic *elastic.Client `inject:""`
}

ElasticRepository is the Gutenfinder interface to Elasticsearch.

type ElasticWorkers

type ElasticWorkers struct {
	Workers     int
	BulkActions int
	BulkSize    int
}

type EncodedFilePath

type EncodedFilePath struct {
	FilePath string
	Encoding TextEncodingID
}

EncodedFilePath is a FilePath with a known encoding.

func (EncodedFilePath) FileExists

func (encpath EncodedFilePath) FileExists() bool

FileExists returns true if the file referenced by the file path exists (and is not a directory).

func (EncodedFilePath) ReadAll

func (encpath EncodedFilePath) ReadAll(ctx context.Context) ([]byte, error)

ReadAll returns the contents of the file, decoded with respect the encoding.

func (EncodedFilePath) ReadCloser

func (encpath EncodedFilePath) ReadCloser(ctx context.Context) (io.ReadCloser, error)

ReadCloser returns a reader for the file.

type Entity

type Entity struct {
	ID int64 `json:"id"`
}

Entity is the supertype of all database objects.

func (*Entity) IDString

func (entity *Entity) IDString() string

IDString returns the ID formatted as a string.

func (*Entity) IsPersisted

func (entity *Entity) IsPersisted() bool

IsPersisted returns true if the entity has an ID.

type Finder

type Finder interface {
	// FindSearchResult gets a SearchResult matching the Search query.
	FindSearchResult(ctx context.Context, search *Search) (*SearchResult, error)
}

Finder discovers new SearchResults.

type FinderFactory

type FinderFactory interface {
	// Build creates a new Finder.
	Build() Finder
}

FinderFactory is an abstraction that builds the Finder. Finder is a complex object and difficult to instantiate through dependency injection. Use this to create Finder with dependency injection.

type FinderFactoryImpl

type FinderFactoryImpl struct {
	DB                      SqlDB                      `inject:""`
	ElasticEBookRepository  ElasticEBookRepository     `inject:""`
	ElasticAuthorRepository ElasticAuthorRepository    `inject:""`
	SearchResultItemRepo    SearchResultItemRepository `inject:""`
	SearchRepo              SearchRepository           `inject:""`
	SearchResultRepo        SearchResultRepository     `inject:""`
}

func (*FinderFactoryImpl) Build

func (factory *FinderFactoryImpl) Build() Finder

type FinderImpl

type FinderImpl struct {
	FinderResultCache FinderResultCache
	Sources           []FinderSource
}

FinderImpl generates SearchResults.

func (*FinderImpl) FindSearchResult

func (finder *FinderImpl) FindSearchResult(ctx context.Context, search *Search) (*SearchResult, error)

FindSearchResult gets a SearchResult matching the Search query.

type FinderResultCache

type FinderResultCache interface {
	// FindCachedResult looks up cached results.
	FindCachedResult(ctx context.Context, search *Search) (*SearchResult, error)
	// CacheResult updates the cache with results.
	CacheResult(ctx context.Context, result *SearchResult) error
}

FinderResultCache is a cache that allows Finder to store results that may take a long time to regenerate.

type FinderSource

type FinderSource interface {
	// FindResultItems is a search task that discovers SearchResultItems.
	FindResultItems(ctx context.Context, search *Search) ([]*SearchResultItem, error)
}

FinderSource is a search task for Finder.

type LandingController

type LandingController struct {
	ViewController `inject:"inline"`
}

LandingController is the controller for serving the landing page.

func (*LandingController) HandleWebRequest

func (controller *LandingController) HandleWebRequest(ctx context.Context, w http.ResponseWriter, request *protocol.Request)

HandleWebRequest handles the HTTP request for the landing page.

type LandingViewModel

type LandingViewModel struct {
	Title    string
	Headline string
}

LandingViewModel is passed to the view to represent the landing page.

type LogLevel

type LogLevel uint8

LogLevel defines the level of detail that will be logged in Gutenfinder.

func (LogLevel) String

func (level LogLevel) String() string

type Migrator

type Migrator struct {
	SourceURL          string
	DatabaseName       string
	MigrationsTable    string
	PostgresConnection string
	// contains filtered or unexported fields
}

Migrator provides all the information needed to perform a database migration.

func (*Migrator) Down

func (migrator *Migrator) Down() error

Down migrates the database to the earliest version.

func (*Migrator) Drop

func (migrator *Migrator) Drop() error

Drop deletes everything in the database.

func (*Migrator) ToVersion

func (migrator *Migrator) ToVersion(version uint) error

ToVersion migrates the database to the given version.

func (*Migrator) Up

func (migrator *Migrator) Up() error

Up migrates the database to the latest version.

type PropertyKey

type PropertyKey string

PropertyKey is the name of an EBook document property.

type PropertyMap

type PropertyMap map[PropertyKey]string

PropertyMap is a semi-structured collection of named properties.

func (*PropertyMap) Scan

func (p *PropertyMap) Scan(src interface{}) error

Scan reads a database value into the PropertyMap.

func (PropertyMap) Value

func (p PropertyMap) Value() (driver.Value, error)

Value creates a database value for the PropertyMap.

type RepoFinderResultCache

type RepoFinderResultCache struct {
	DB                   SqlDB
	FinderResultCache    FinderResultCache
	SearchResultItemRepo SearchResultItemRepository
	SearchRepo           SearchRepository
	SearchResultRepo     SearchResultRepository
}

func (*RepoFinderResultCache) CacheResult

func (cache *RepoFinderResultCache) CacheResult(ctx context.Context, searchResult *SearchResult) error

func (*RepoFinderResultCache) FindCachedResult

func (cache *RepoFinderResultCache) FindCachedResult(ctx context.Context, search *Search) (*SearchResult, error)

type Repository

type Repository struct {
	DB SqlDB `inject:""`
}

Repository is the supertype for Repository-style database interfaces.

type RequestHandler

type RequestHandler interface {
	// HandleRequest handles the given protocol Request and returns an appropriate protocol Response.
	HandleRequest(ctx context.Context, request *protocol.Request) *protocol.Response
}

RequestHandler represents a controller that responds to a protocol request.

type RootController

type RootController struct {
	sync.RWMutex

	WebController        WebController        `inject:"inline"`
	WebsocketController  WebsocketController  `inject:"inline"`
	WebAPIController     WebAPIController     `inject:"inline"`
	StaticFileController StaticFileController `inject:"inline"`
	// contains filtered or unexported fields
}

RootController is root of the Gutenfinder web interface.

func (*RootController) ListenAndServe

func (controller *RootController) ListenAndServe(address string) error

ListenAndServe serves HTTP on the given host:port address.

func (*RootController) ServeHTTP

func (controller *RootController) ServeHTTP(w http.ResponseWriter, r *http.Request)

type Scanner

type Scanner interface {
	// SetMaxFiles sets the maximum number of files that the scanner will open concurrently.
	SetMaxFiles(maxOpenFiles int64)
	// ScanXMLFilesRecursively loads EBooks from any catalogue file found under the rootDirectory.
	ScanXMLFilesRecursively(ctx context.Context, rootDirectory string) (<-chan *EBook, error)
	// ScanXMLReaders will load EBooks from catalogue files represented by the given readers channel.
	ScanXMLReaders(readers <-chan io.ReadCloser) (<-chan *EBook, error)
	// LoadAllText loads the text files for each eBook, and returns them as ElasticEBooks on a channel.
	LoadAllText(ctx context.Context, eg *errgroup.Group, eBooks ...*EBook) <-chan *ElasticEBook
	// AttachLocalFiles finds all local files for the given EBooks, and returns the EBooks for which local files were successfully attached.
	AttachLocalFiles(root string, eBookChan <-chan *EBook) (<-chan *EBook, error)
}

type ScannerImpl

type ScannerImpl struct {
	// contains filtered or unexported fields
}

ScannerImpl loads Project Gutenberg EBooks into our databases.

func (*ScannerImpl) AttachLocalFiles

func (scanner *ScannerImpl) AttachLocalFiles(root string, eBookChan <-chan *EBook) (<-chan *EBook, error)

AttachLocalFiles finds all local files for the given EBooks, and returns the EBooks for which local files were successfully attached.

func (*ScannerImpl) LoadAllText

func (scanner *ScannerImpl) LoadAllText(ctx context.Context, eg *errgroup.Group, eBooks ...*EBook) <-chan *ElasticEBook

LoadAllText loads the text files for each eBook, and returns them as ElasticEBooks on a channel.

func (*ScannerImpl) ScanXMLFilesRecursively

func (scanner *ScannerImpl) ScanXMLFilesRecursively(ctx context.Context, rootDirectory string) (<-chan *EBook, error)

ScanXMLFilesRecursively loads EBooks from any catalogue file found under the rootDirectory.

func (*ScannerImpl) ScanXMLReaders

func (scanner *ScannerImpl) ScanXMLReaders(readers <-chan io.ReadCloser) (<-chan *EBook, error)

ScanXMLReaders will load EBooks from catalogue files represented by the given readers channel.

func (*ScannerImpl) SetMaxFiles

func (scanner *ScannerImpl) SetMaxFiles(maxOpenFiles int64)

SetMaxFiles sets the maximum number of files that the scanner will open concurrently.

type Search struct {
	Entity
	Term    string
	Results []*SearchResult
}

Search is a term entered by a user, when requesting a SearchResult.

func (*Search) Identity

func (search *Search) Identity() string

Identity provides an summary of the Search's identity, whether or not it is persisted.

type SearchController

type SearchController struct {
	ViewController `inject:"inline"`
	FinderFactory  FinderFactory `inject:""`
}

SearchController provides Search for the Gutenfinder webservice.

func (*SearchController) HandleRequest

func (controller *SearchController) HandleRequest(ctx context.Context, request *protocol.Request) *protocol.Response

HandleRequest performs a Search on the term parameter provided in the Request. See SearchControllerTermParameter.

type SearchOptionFunc

type SearchOptionFunc func(service *elastic.SearchService)

SearchOptionFunc provides options for elastic.SearchService.

type SearchRepository

type SearchRepository interface {
	// EnsureExists returns true if a new search is created, false otherwise.  If the search term matches a term stored in the model, the search Id will be updated to match the model.
	EnsureExists(ctx context.Context, tx Tx, search *Search) (bool, error)
	// Get finds a Search by its ID.  If there is no such ID, an error is returned.
	Get(ctx context.Context, tx Tx, id int64) (*Search, error)
	// Find searches for a saved search by its term.  The returned search does not contain any associated results.  If no search is found, nil is returned in place of the Search.
	Find(ctx context.Context, tx Tx, term string) (*Search, error)
	// Save will insert or update the given Searches as appropriate.
	Save(ctx context.Context, tx Tx, search ...*Search) error
}

type SearchRepositoryImpl

type SearchRepositoryImpl struct {
	Repository `inject:"inline"`
	ResultRepo SearchResultRepositoryImpl `inject:"inline"`
}

SearchRepositoryImpl is a database interface for Search.

func (SearchRepositoryImpl) EnsureExists

func (repo SearchRepositoryImpl) EnsureExists(ctx context.Context, tx Tx, search *Search) (bool, error)

EnsureExists returns true if a new search is created, false otherwise. If the search term matches a term stored in the model, the search Id will be updated to match the model.

func (SearchRepositoryImpl) Find

func (repo SearchRepositoryImpl) Find(ctx context.Context, tx Tx, term string) (*Search, error)

Find searches for a saved search by its term. The returned search does not contain any associated results. If no search is found, nil is returned in place of the Search.

func (SearchRepositoryImpl) Get

func (repo SearchRepositoryImpl) Get(ctx context.Context, tx Tx, id int64) (*Search, error)

Get finds a Search by its ID. If there is no such ID, an error is returned.

func (SearchRepositoryImpl) Save

func (repo SearchRepositoryImpl) Save(ctx context.Context, tx Tx, search ...*Search) error

Save will insert or update the given Searches as appropriate.

type SearchResult

type SearchResult struct {
	Entity
	CatalogueUpdate *CatalogueUpdate    `json:"-"`
	Search          *Search             `json:"-"`
	CreateTime      time.Time           `json:"create_time"`
	Items           []*SearchResultItem `json:"items"`
}

SearchResult is a collection of all the items found when searching our EBook catalogue.

func (*SearchResult) Identity

func (searchResult *SearchResult) Identity() string

Identity provides an summary of the SearchResults's identity, whether or not it is persisted.

func (*SearchResult) IsAttached

func (searchResult *SearchResult) IsAttached() bool

IsAttached returns true if the SearchResult is attached to its parent structure.

func (*SearchResult) String

func (searchResult *SearchResult) String() string

func (*SearchResult) UpdateItemsOwner

func (searchResult *SearchResult) UpdateItemsOwner()

UpdateItemsOwner ensures that the child items are linked to this search result.

type SearchResultItem

type SearchResultItem struct {
	Entity
	SearchResult      *SearchResult                `json:"-"`
	Type              SearchResultItemTypeID       `json:"type"`
	Sequence          int64                        `json:"sequence"`
	TextResult        *TextSearchResultItem        `json:"text_result,omitempty"`
	TitleResult       *TitleSearchResultItem       `json:"title_result,omitempty"`
	AuthorAliasResult *AuthorAliasSearchResultItem `json:"author_alias_result,omitempty"`
}

SearchResultItem is a piece of data retreived by searching our EBook catalogue.

func MakeAuthorAliasSearchResultItem

func MakeAuthorAliasSearchResultItem(author *Author, authorAlias string) *SearchResultItem

MakeAuthorAliasSearchResultItem creates a SearchResultItem matching the given Author's given alias.

func MakeTextSearchResultItem

func MakeTextSearchResultItem(eBook *EBook, snippet string) *SearchResultItem

MakeTextSearchResultItem creates a SearchResultItem matching the snippet in the given EBook.

func MakeTitleSearchResultItem

func MakeTitleSearchResultItem(eBook *EBook) *SearchResultItem

MakeTitleSearchResultItem creates a SearchResultItem matching the given EBook's title.

func (*SearchResultItem) GetEBook

func (searchResultItem *SearchResultItem) GetEBook() (*EBook, error)

GetEBook returns the EBook attached to the SearchResultItem, if available.

func (*SearchResultItem) IsAttached

func (searchResultItem *SearchResultItem) IsAttached() bool

IsAttached returns true if the SearchResultItem is linked to its parent structure.

func (*SearchResultItem) IsSearchResultTypeAttached

func (searchResultItem *SearchResultItem) IsSearchResultTypeAttached() bool

IsSearchResultTypeAttached returns true if the SearchResultItem is linked to its child structure.

func (*SearchResultItem) String

func (searchResultItem *SearchResultItem) String() string

type SearchResultItemController

type SearchResultItemController struct {
	ViewController             `inject:"inline"`
	SearchResultItemRepository SearchResultItemRepositoryImpl `inject:"inline"`
	EBookRepository            EBookRepositoryImpl            `inject:"inline"`
	DB                         SqlDB                          `inject:""`
}

SearchResultItemController is a controller for SearchResultItems.

func (*SearchResultItemController) HandleRequest

func (controller *SearchResultItemController) HandleRequest(ctx context.Context, request *protocol.Request) *protocol.Response

HandleRequest performs a Search on the term parameter provided in the Request. See SearchControllerTermParameter.

type SearchResultItemRepository

type SearchResultItemRepository interface {
	// Get retrieves a SearchResultItem by its ID.  If the SearchResultItem is not found, an error is returned.
	Get(ctx context.Context, tx Tx, id int64) (*SearchResultItem, error)
	// Save will insert or update the given SearchResultItems as appropriate.
	Save(ctx context.Context, tx Tx, searchResultItem ...*SearchResultItem) error
	// ListForSearchResult finds all SearchResultItem that are associated with the given searchResult.  Any eBooks linked will contain their properties, but not files.
	ListForSearchResult(ctx context.Context, tx Tx, searchResult *SearchResult) ([]*SearchResultItem, error)
}

type SearchResultItemRepositoryImpl

type SearchResultItemRepositoryImpl struct {
	Repository      `inject:"inline"`
	TextRepo        TextSearchResultItemRepositoryImpl        `inject:"inline"`
	TitleRepo       TitleSearchResultItemRepositoryImpl       `inject:"inline"`
	AuthorAliasRepo AuthorAliasSearchResultItemRepositoryImpl `inject:"inline"`
}

SearchResultItemRepositoryImpl is a database interface for SearchResultItems.

func (SearchResultItemRepositoryImpl) Get

Get retrieves a SearchResultItem by its ID. If the SearchResultItem is not found, an error is returned.

func (SearchResultItemRepositoryImpl) ListForSearchResult

func (repo SearchResultItemRepositoryImpl) ListForSearchResult(ctx context.Context, tx Tx, searchResult *SearchResult) ([]*SearchResultItem, error)

ListForSearchResult finds all SearchResultItem that are associated with the given searchResult. Any eBooks linked will contain their properties, but not files.

func (SearchResultItemRepositoryImpl) Save

func (repo SearchResultItemRepositoryImpl) Save(ctx context.Context, tx Tx, searchResultItem ...*SearchResultItem) error

Save will insert or update the given SearchResultItems as appropriate.

type SearchResultItemTypeID

type SearchResultItemTypeID int64

SearchResultItemTypeID is a numeric identifier for subtypes of SearchResultItemType, suitable for persisting in the database.

func (SearchResultItemTypeID) Precedence

func (typeID SearchResultItemTypeID) Precedence() int

Precedence returns the "importance" of a search result item type. Higher is more important.

func (SearchResultItemTypeID) String

func (typeID SearchResultItemTypeID) String() string

type SearchResultItemViewModel

type SearchResultItemViewModel struct {
	SearchResultItemID int64         `json:"id"`
	AuthorID           int64         `json:"author_id,omitempty"`
	AuthorAlias        string        `json:"author_alias,omitempty"`
	EBookID            int64         `json:"ebook_id,omitempty"`
	EBookTitle         string        `json:"ebook_title,omitempty"`
	Snippet            template.HTML `json:"html_snippet"`
}

SearchResultItemViewModel is passed to the view to represent a SearchResultItem.

func MakeSearchResultItemViewModel

func MakeSearchResultItemViewModel(item *SearchResultItem) (*SearchResultItemViewModel, error)

MakeSearchResultItemViewModel creates a view model for a SearchResultItem.

type SearchResultRepository

type SearchResultRepository interface {
	// FindRecent finds a SearchResult matching the given Search if the SearchResult was generated for the last catalogue update.
	FindRecent(ctx context.Context, tx Tx, search *Search) (*SearchResult, error)
	// Get retrieves a SearchResult by its ID.  If there is no such SearchResult, an error is returned.
	Get(ctx context.Context, tx Tx, id int64) (*SearchResult, error)
	// ListForSearch returns all SearchResults that reference the given Search.  The returned SearchResults do not include SearchResultItems.
	ListForSearch(ctx context.Context, tx Tx, search *Search) ([]*SearchResult, error)
	// Save will insert or update the given SearchResults as appropriate.
	Save(ctx context.Context, tx Tx, searchResult ...*SearchResult) error
}

type SearchResultRepositoryImpl

type SearchResultRepositoryImpl struct {
	Repository `inject:"inline"`
	ItemRepo   SearchResultItemRepositoryImpl `inject:"inline"`
}

SearchResultRepositoryImpl is a database interface for SearchResults.

func (SearchResultRepositoryImpl) FindRecent

func (repo SearchResultRepositoryImpl) FindRecent(ctx context.Context, tx Tx, search *Search) (*SearchResult, error)

FindRecent finds a SearchResult matching the given Search if the SearchResult was generated for the last catalogue update.

func (SearchResultRepositoryImpl) Get

Get retrieves a SearchResult by its ID. If there is no such SearchResult, an error is returned.

func (SearchResultRepositoryImpl) ListForSearch

func (repo SearchResultRepositoryImpl) ListForSearch(ctx context.Context, tx Tx, search *Search) ([]*SearchResult, error)

ListForSearch returns all SearchResults that reference the given Search. The returned SearchResults do not include SearchResultItems.

func (SearchResultRepositoryImpl) Save

func (repo SearchResultRepositoryImpl) Save(ctx context.Context, tx Tx, searchResult ...*SearchResult) error

Save will insert or update the given SearchResults as appropriate.

type SearchResultViewModel

type SearchResultViewModel struct {
	SearchResultID int64                        `json:"id"`
	Term           string                       `json:"term"`
	ResultCount    int                          `json:"result_count"`
	Items          []*SearchResultItemViewModel `json:"items"`
}

SearchResultViewModel is passed to the view to represent a SearchResult.

func MakeSearchResultViewModel

func MakeSearchResultViewModel(searchResult *SearchResult) (*SearchResultViewModel, error)

MakeSearchResultViewModel creates a view model for a SearchResult.

type SqlDB

type SqlDB interface {
	io.Closer
	BeginTxx(ctx context.Context, opts *sql.TxOptions) (Tx, error)
}

type SqlxDB

type SqlxDB sqlx.DB

func (*SqlxDB) BeginTxx

func (db *SqlxDB) BeginTxx(ctx context.Context, opts *sql.TxOptions) (Tx, error)

type StaticFileController

type StaticFileController struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

StaticFileController is a controller for static files.

func (*StaticFileController) ServeHTTP

func (controller *StaticFileController) ServeHTTP(w http.ResponseWriter, r *http.Request)

type StudyEBookViewModel

type StudyEBookViewModel struct {
	EBookID          int64    `json:"id"`
	EBookGutenbergID string   `json:"gutenberg_id"`
	Paragraphs       []string `json:"paragraphs"`
}

StudyEBookViewModel is passed to the view to display the text of an EBook.

func MakeStudyEBookViewModel

func MakeStudyEBookViewModel(eBook *EBook, paragraphs []string) *StudyEBookViewModel

MakeStudyEBookViewModel creates a ViewModel for the given EBook.

type TemplateView

type TemplateView struct {
	Paths       []string
	AssetBundle AssetBundle

	sync.RWMutex
	// contains filtered or unexported fields
}

TemplateView is an View based on Go templates.

func (*TemplateView) Render

func (view *TemplateView) Render(w io.Writer, viewName string, viewModel interface{}) error

Render writes the processed template to the writer.

type TextEncodingID

type TextEncodingID int

TextEncodingID is a numeric identifier that refers to types of character encoding found in the Project Gutenberg catalogue.

func (TextEncodingID) Reader

func (encoding TextEncodingID) Reader(reader io.Reader) io.Reader

Reader wraps the given reader such that the contents will decode to UTF-8.

func (TextEncodingID) String

func (encoding TextEncodingID) String() string

type TextSearchResultItem

type TextSearchResultItem struct {
	EBook   *EBook `json:"ebook"`
	Snippet string `json:"snippet"`
	// contains filtered or unexported fields
}

TextSearchResultItem is a SearchResultItemType that references text within an EBook.

func (*TextSearchResultItem) IsAttached

func (textSearchResultItem *TextSearchResultItem) IsAttached() bool

IsAttached returns true if the TextSearchResultItem is attached to an EBook.

func (*TextSearchResultItem) String

func (textSearchResultItem *TextSearchResultItem) String() string

type TextSearchResultItemRepository

type TextSearchResultItemRepository interface {
	// Get retrieves a TextSearchResultItem by its ID.  An error is returned if the TextSearchResultItem is not found.
	Get(ctx context.Context, tx Tx, id int64) (*TextSearchResultItem, error)
	// Save will insert or update the given TextSearchResultItems as appropriate.
	Save(ctx context.Context, tx Tx, textSearchResultItem ...*TextSearchResultItem) error
}

type TextSearchResultItemRepositoryImpl

type TextSearchResultItemRepositoryImpl struct {
	Repository `inject:"inline"`
}

TextSearchResultItemRepositoryImpl is a database interface for TextSearchResultItems.

func (TextSearchResultItemRepositoryImpl) Get

Get retrieves a TextSearchResultItem by its ID. An error is returned if the TextSearchResultItem is not found.

func (TextSearchResultItemRepositoryImpl) Save

func (repo TextSearchResultItemRepositoryImpl) Save(ctx context.Context, tx Tx, textSearchResultItem ...*TextSearchResultItem) error

Save will insert or update the given TextSearchResultItems as appropriate.

type TitleSearchResultItem

type TitleSearchResultItem struct {
	EBook *EBook `json:"ebook"`
	// contains filtered or unexported fields
}

TitleSearchResultItem is a SearchResultItemType that references an EBook's title.

func (*TitleSearchResultItem) IsAttached

func (titleSearchResultItem *TitleSearchResultItem) IsAttached() bool

IsAttached returns true if the TitleSearchResultItem is linked to an EBook.

func (*TitleSearchResultItem) String

func (titleSearchResultItem *TitleSearchResultItem) String() string

type TitleSearchResultItemRepository

type TitleSearchResultItemRepository interface {
	// Get retrieves a TitleSearchResultItem by ID.  An error will be returned if a TitleSearchResultItem cannot be found.
	Get(ctx context.Context, tx Tx, id int64) (*TitleSearchResultItem, error)
	// Save will insert or update the given TitleSearchResultItems as appropriate.
	Save(ctx context.Context, tx Tx, titleSearchResultItem ...*TitleSearchResultItem) error
}

type TitleSearchResultItemRepositoryImpl

type TitleSearchResultItemRepositoryImpl struct {
	Repository `inject:"inline"`
}

TitleSearchResultItemRepositoryImpl is a database interface for TitleSearchResultItems.

func (TitleSearchResultItemRepositoryImpl) Get

Get retrieves a TitleSearchResultItem by ID. An error will be returned if a TitleSearchResultItem cannot be found.

func (TitleSearchResultItemRepositoryImpl) Save

func (repo TitleSearchResultItemRepositoryImpl) Save(ctx context.Context, tx Tx, titleSearchResultItem ...*TitleSearchResultItem) error

Save will insert or update the given TitleSearchResultItems as appropriate.

type Tx

type Tx interface {
	sqlx.QueryerContext
	sqlx.ExecerContext
	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
	Rollback() error
	Commit() error
}

Tx is an abstraction of sql.Tx.

type View

type View interface {
	Render(w io.Writer, viewName string, viewModel interface{}) error
}

View renders the named view to the writer.

func MakeAssetTemplateView

func MakeAssetTemplateView() View

MakeAssetTemplateView creates a TemplateView for the Gutenfinder templates.

type ViewController

type ViewController struct {
	View View `inject:""`
}

ViewController represents a controller that has a view.

type WebAPIController

type WebAPIController struct {
	APIRouteController         `inject:"inline"`
	SearchController           SearchController           `inject:"inline"`
	SearchResultItemController SearchResultItemController `inject:"inline"`
}

WebAPIController serves an API over HTTP.

func (*WebAPIController) HandleWebRequest

func (controller *WebAPIController) HandleWebRequest(ctx context.Context, w http.ResponseWriter, request *protocol.Request)

HandleWebRequest handles a protocol request that was originally made over plain HTTP.

func (*WebAPIController) ServeHTTP

func (controller *WebAPIController) ServeHTTP(w http.ResponseWriter, r *http.Request)

type WebController

type WebController struct {
	WebRouteController `inject:"inline"`
}

WebController serves HTML over HTTP.

func (*WebController) ServeHTTP

func (controller *WebController) ServeHTTP(w http.ResponseWriter, r *http.Request)

type WebRequestHandler

type WebRequestHandler interface {
	HandleWebRequest(ctx context.Context, w http.ResponseWriter, req *protocol.Request)
}

WebRequestHandler represents a controller that responds to a protocol request that originated over plan HTTP.

type WebRouteController

type WebRouteController struct {
	sync.RWMutex

	LandingController LandingController `inject:"inline"`
	// contains filtered or unexported fields
}

WebRouteController serves HTML over HTTP.

func (*WebRouteController) HandleWebRequest

func (controller *WebRouteController) HandleWebRequest(ctx context.Context, w http.ResponseWriter, request *protocol.Request)

HandleWebRequest handles a protocol Request that originated over plain HTTP.

func (*WebRouteController) ServeHTTP

func (controller *WebRouteController) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*WebRouteController) SetRoutes

func (controller *WebRouteController) SetRoutes(routes ...WebRoutingOption)

SetRoutes defines the routes available to the WebRouteController.

type WebRoutingOption

type WebRoutingOption func(controller *WebRouteController)

WebRoutingOption is used to set up an WebRouteController.

func AddWebRoute

func AddWebRoute(resource string, handler WebRequestHandler) WebRoutingOption

AddWebRoute is an WebRoutingOption that sets a route on the WebRouteController.

type WebsocketController

type WebsocketController struct {
	APIRouteController         `inject:"inline"`
	SearchController           SearchController           `inject:"inline"`
	SearchResultItemController SearchResultItemController `inject:"inline"`
}

WebsocketController serves an API over Websockets.

func (*WebsocketController) ServeHTTP

func (controller *WebsocketController) ServeHTTP(w http.ResponseWriter, r *http.Request)

Source Files

Directories

Path Synopsis
Package cli is a facade to the gutenfinder package that implements the behaviour needed for the Gutenfinder CLI application.
Package cli is a facade to the gutenfinder package that implements the behaviour needed for the Gutenfinder CLI application.
Gutenfinder CLI application.
Gutenfinder CLI application.
cmd
Package integration is a test-only package containing integration tests for gutenfinder.
Package integration is a test-only package containing integration tests for gutenfinder.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL