scope/internal/cards/cards.go

104 lines
2.6 KiB
Go

/*
* Scope - A simple and minimal metasearch engine
* Copyright (C) 2021 Arsen Musayelyan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package cards
import (
"html/template"
"sort"
)
// cardRegistration represents a card that has been registered
type cardRegistration struct {
name string
priority int
newFn NewCardFunc
}
// cards stores all registered cards
var cards = []cardRegistration{}
// NewCardFunc creates and returns a new card.
// This should not be an expensive operation
type NewCardFunc func(query, userAgent string) Card
// Card represents a search result card
type Card interface {
// RunQuery runs any HTTP or other requests
RunQuery() error
// Returned returns whether the query
// returned any information
Returned() bool
// Matches returns whether the query matches
// for the card
Matches() bool
// StripKey removes the key words and returns
// the updated query
StripKey() string
// Title returns the card title
Title() string
// Content returns the contents of the card
Content() template.HTML
// Footer returns the contents of the card footer
Footer() template.HTML
// Head returns any extras to include in <head>
Head() template.HTML
}
// Register adds a new card to the library
func Register(name string, priority int, fn NewCardFunc) {
// For every registered card
for _, cardReg := range cards {
// If priority already exists, increase
if cardReg.priority == priority {
priority++
}
// If card already registered, return
if cardReg.name == name {
return
}
}
// Add card to slice
cards = append(cards, cardRegistration{name, priority, fn})
}
// GetCard returns a matching registered card
func GetCard(query, userAgent string) Card {
// Sort slice by priority
sort.Slice(cards, func(i, j int) bool {
return cards[i].priority < cards[j].priority
})
// For every registered card
for _, cardReg := range cards {
// Create new card
card := cardReg.newFn(query, userAgent)
// If card matches, return it
if card.Matches() {
return card
}
}
return nil
}