search-web-api 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +307 -0
- package/demo/index.ts +38 -0
- package/demo/openapi.ts +402 -0
- package/demo/routes/autocomplete.ts +124 -0
- package/demo/routes/search.ts +61 -0
- package/docs/AUTOCOMPLETE.md +296 -0
- package/docs/CATEGORY_SEARCH.md +265 -0
- package/package.json +32 -0
- package/src/autocomplete/autocomplete-ai-next-word-predictor.ts +47 -0
- package/src/autocomplete/autocomplete-search-engine-backends.ts +231 -0
- package/src/category-registry.ts +6 -0
- package/src/config/search-engine-constants.ts +216 -0
- package/src/constants.ts +6 -0
- package/src/engine-descriptions.ts +7 -0
- package/src/engine-status.ts +7 -0
- package/src/engine.ts +6 -0
- package/src/registry/search-engine-category-registry.ts +200 -0
- package/src/registry/search-engine-descriptions.ts +121 -0
- package/src/registry/search-engine-status-tracker.ts +240 -0
- package/src/result-container.ts +8 -0
- package/src/search/search-engines-registry-list.ts +205 -0
- package/src/search/search-query-executor.ts +168 -0
- package/src/search/search-result-container.ts +421 -0
- package/src/search-web-types.ts +7 -0
- package/src/search.ts +10 -0
- package/src/sources/academic/arxiv.ts +72 -0
- package/src/sources/academic/core.ts +65 -0
- package/src/sources/academic/crossref.ts +75 -0
- package/src/sources/academic/doaj.ts +63 -0
- package/src/sources/academic/google_scholar.ts +53 -0
- package/src/sources/academic/openalex.ts +75 -0
- package/src/sources/academic/pubmed.ts +96 -0
- package/src/sources/academic/semantic_scholar.ts +77 -0
- package/src/sources/academic/wikidata.ts +44 -0
- package/src/sources/general/baidu.ts +59 -0
- package/src/sources/general/bing.ts +30 -0
- package/src/sources/general/brave.ts +54 -0
- package/src/sources/general/duckduckgo.ts +49 -0
- package/src/sources/general/google.ts +68 -0
- package/src/sources/general/mojeek.ts +56 -0
- package/src/sources/general/qwant.ts +37 -0
- package/src/sources/general/startpage.ts +44 -0
- package/src/sources/general/yahoo.ts +41 -0
- package/src/sources/general/yandex.ts +56 -0
- package/src/sources/images/bing_images.ts +68 -0
- package/src/sources/images/deviantart.ts +71 -0
- package/src/sources/images/flickr.ts +132 -0
- package/src/sources/images/google_images.ts +101 -0
- package/src/sources/images/imgur.ts +58 -0
- package/src/sources/images/openclipart.ts +52 -0
- package/src/sources/images/pixabay.ts +56 -0
- package/src/sources/images/unsplash.ts +38 -0
- package/src/sources/images/wallhaven.ts +50 -0
- package/src/sources/it/crates.ts +41 -0
- package/src/sources/it/dockerhub.ts +47 -0
- package/src/sources/it/github.ts +37 -0
- package/src/sources/it/gitlab.ts +55 -0
- package/src/sources/it/npm.ts +36 -0
- package/src/sources/it/packagist.ts +43 -0
- package/src/sources/it/pypi.ts +30 -0
- package/src/sources/it/rubygems.ts +43 -0
- package/src/sources/it/stackoverflow.ts +39 -0
- package/src/sources/maps/apple_maps.ts +105 -0
- package/src/sources/maps/openstreetmap.ts +34 -0
- package/src/sources/maps/photon.ts +77 -0
- package/src/sources/news/bing_news.ts +95 -0
- package/src/sources/news/google_news.ts +80 -0
- package/src/sources/news/hackernews.ts +94 -0
- package/src/sources/news/yahoo_news.ts +77 -0
- package/src/sources/shopping/ebay.ts +96 -0
- package/src/sources/social/mastodon.ts +46 -0
- package/src/sources/social/medium.ts +52 -0
- package/src/sources/social/reddit.ts +48 -0
- package/src/sources/social/soundcloud.ts +64 -0
- package/src/sources/social/twitter.ts +56 -0
- package/src/sources/specialized/annas_archive.ts +97 -0
- package/src/sources/specialized/archive.ts +48 -0
- package/src/sources/specialized/genius.ts +43 -0
- package/src/sources/specialized/goodreads.ts +62 -0
- package/src/sources/specialized/imdb.ts +55 -0
- package/src/sources/specialized/openlibrary.ts +59 -0
- package/src/sources/specialized/wikipedia.ts +37 -0
- package/src/sources/specialized/wttr.ts +98 -0
- package/src/sources/torrents/1337x.ts +43 -0
- package/src/sources/torrents/eztv.ts +47 -0
- package/src/sources/torrents/kickass.ts +63 -0
- package/src/sources/torrents/nyaa.ts +53 -0
- package/src/sources/torrents/solidtorrents.ts +68 -0
- package/src/sources/torrents/thepiratebay.ts +57 -0
- package/src/sources/torrents/yts.ts +54 -0
- package/src/sources/videos/bing_videos.ts +91 -0
- package/src/sources/videos/dailymotion.ts +101 -0
- package/src/sources/videos/invidious.ts +86 -0
- package/src/sources/videos/peertube.ts +76 -0
- package/src/sources/videos/vimeo.ts +67 -0
- package/src/sources/videos/youtube.ts +78 -0
- package/src/suggest-next-words/autocomplete-ai.ts +38 -0
- package/src/suggest-next-words/autocomplete-search-engines.ts +384 -0
- package/src/suggest-next-words/misspelled-typos-8k.json +1 -0
- package/src/types/search-engine-interface.ts +27 -0
- package/src/types/search-result-types.ts +405 -0
- package/test/api.test.ts +128 -0
- package/test/autocomplete-ai.test.ts +20 -0
- package/test/autocomplete-engines.test.ts +131 -0
- package/test/engine-health-suite.test.ts +350 -0
- package/test/search.test.ts +69 -0
- package/test/sources-unit.test.ts +1152 -0
- package/test/sources.test.ts +182 -0
- package/test/test-utils.ts +81 -0
- package/tsconfig.json +16 -0
- package/vitest.config.ts +20 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search Engine Descriptions — Human-readable descriptions for every search
|
|
3
|
+
* engine adapter in this package, sourced from SearXNG's engine_descriptions.json
|
|
4
|
+
* and extended with engines specific to this implementation. Used for API
|
|
5
|
+
* documentation, UI tooltips, and README generation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const engineDescriptions: { [key: string]: string } = {
|
|
9
|
+
"1337x":
|
|
10
|
+
"1337x is a website that provides a directory of torrent files and magnet links used for peer-to-peer file sharing through the BitTorrent protocol. It is primarily used to facilitate online piracy.",
|
|
11
|
+
annas_archive:
|
|
12
|
+
'Anna\'s Archive is an open source search engine for shadow libraries that was launched by the pseudonymous Anna shortly after law enforcement efforts to shut down Z-Library in 2022. The site aggregates records from Z-Library, Sci-Hub, and Library Genesis (LibGen), among other sources. It calls itself "the largest truly open library in human history", and has said it aims to "catalog all the books in existence" and "track humanity\'s progress toward making all these books easily available i...',
|
|
13
|
+
apple_maps:
|
|
14
|
+
'Apple Maps is a web mapping service developed by Apple. As the default map system of iOS, iPadOS, macOS, tvOS, visionOS, and watchOS, it provides directions and estimated times of arrival for driving, walking, cycling, and public transportation navigation. A "Flyover" mode shows certain urban centers and other places of interest in a 3D landscape composed of models of buildings and structures.',
|
|
15
|
+
arxiv:
|
|
16
|
+
"arXiv is an open-access repository of electronic preprints and postprints approved for posting after moderation, but not peer reviewed. It consists of scientific papers in the fields of mathematics, physics, astronomy, electrical engineering, computer science, quantitative biology, statistics, mathematical finance, and economics, which can be accessed online. In many fields of mathematics and physics, almost all scientific papers are self-archived on the arXiv repository before publication in...",
|
|
17
|
+
baidu:
|
|
18
|
+
"Baidu, Inc. is a Chinese multinational technology company specializing in Internet services and artificial intelligence. It holds a dominant position in China's search engine market, and provides a wide variety of other internet services such as Baidu App, Baidu Baike, iQIYI, and Baidu Tieba.",
|
|
19
|
+
bing: "Microsoft Bing is a search engine owned and operated by Microsoft, it is developed by Microsoft AI. The service traces its roots back to Microsoft's earlier search engines, including MSN Search, Windows Live Search, and Live Search. Bing offers a broad spectrum of search services, encompassing web, video, image, and map search products, all developed using ASP.NET.",
|
|
20
|
+
bing_images: "bing:en",
|
|
21
|
+
bing_news: "bing:en",
|
|
22
|
+
brave:
|
|
23
|
+
"Brave is a free and open-source web browser which was first released in 2016. It is developed by US-based Brave Software, Inc. and based on the Chromium web browser. The browser is marketed as a privacy-focused web browser and includes features such as built-in advertisement blocking, protections against browser fingerprinting and a private browsing mode that integrates the Tor anonymity network. Brave also incorporates its own advertising through a rewards system based on cryptocurrency, whi...",
|
|
24
|
+
crates: "crates.io: Rust Package Registry",
|
|
25
|
+
crossref:
|
|
26
|
+
"Crossref is a nonprofit open digital infrastructure organization for the global scholarly research community. It is the largest digital object identifier (DOI) Registration Agency of the International DOI Foundation. It has 19,000 members from 150 countries representing publishers, libraries, research institutions, and funders and was launched in early 2000 as a cooperative effort among publishers to enable persistent cross-platform citation linking in online academic journals. As of July 202...",
|
|
27
|
+
dailymotion:
|
|
28
|
+
"Dailymotion is a French online video sharing platform owned by Canal+. Prior to 2024, it was owned by Vivendi. North American launch partners included Vice Media, Bloomberg, and Hearst Digital Media. Dailymotion was among the first platforms to support HD (720p) resolution video. It is available worldwide in 183 languages and 43 localised versions featuring local home pages and content. It has more than 300 million monthly users.",
|
|
29
|
+
deviantart:
|
|
30
|
+
"DeviantArt is an American online community that features artwork, videography, photography, and literature, launched on August 7, 2000, by Mathew Stephens, Scott Jarkoff and Angelo Sotira, among others.",
|
|
31
|
+
dockerhub: "hosting service for Docker repository",
|
|
32
|
+
flickr:
|
|
33
|
+
"Flickr is an image and video hosting service, as well as an online community, founded in Canada and headquartered in the United States. It was created by Ludicorp in 2004 and was for a time a common way for amateur and professional photographers to host high-resolution photos. Flickr was owned by Yahoo! from 2005 and has been owned by SmugMug since 2018.",
|
|
34
|
+
genius:
|
|
35
|
+
"Genius is an American digital media company founded on August 27, 2009, by Tom Lehman, Ilan Zechory, and Mahbod Moghadam. The company's eponymous website serves as a database for song lyrics, news stories, sources, poetry, and documents, in which users can provide annotations and interpretations for.",
|
|
36
|
+
github:
|
|
37
|
+
"GitHub is a proprietary developer platform that allows developers to create, store, manage, and share their code. It uses Git to provide distributed version control and GitHub itself provides access control, bug tracking, software feature requests, task management, continuous integration, and wikis for every project. GitHub has been a subsidiary of Microsoft since 2018 and its headquarters are located in San Francisco.",
|
|
38
|
+
goodreads:
|
|
39
|
+
"Goodreads is an American social cataloging website operated by Goodreads, Inc., a subsidiary of Amazon. Users can search its database of books, annotations, quotes, and reviews and expand the database by registering books to generate library catalogs and reading lists. They can also create their own groups of book suggestions, surveys, polls, blogs, and discussions. The website's offices are located in San Francisco.",
|
|
40
|
+
google:
|
|
41
|
+
"Google Search is a search engine operated by Google. It allows users to search for information on the Web by entering keywords or phrases. Google Search uses algorithms to analyze and rank websites based on their relevance to the search query. Google Search is the most-visited website in the world. As of 2025, Google Search has a 90% share of the global search engine market. Approximately 24.1% of Google's monthly global traffic comes from the United States, 5.6% from India, 5.5% from Japan, ...",
|
|
42
|
+
google_images:
|
|
43
|
+
"Google Images is a search engine owned by Google that allows users to search the World Wide Web for images. It was introduced on July 12, 2001, due to a demand for pictures of the green Versace dress of Jennifer Lopez worn in February 2000. In 2011, image search functionality was added.",
|
|
44
|
+
google_news:
|
|
45
|
+
"Google News is a news aggregator service developed by Google. It presents a continuous flow of links to articles organized from thousands of publishers and magazines.",
|
|
46
|
+
google_scholar:
|
|
47
|
+
"Google Scholar is a freely accessible web search engine that indexes the full text or metadata of scholarly literature across an array of publishing formats and disciplines. Released in beta in November 2004, the Google Scholar index includes peer-reviewed online academic journals and books, conference papers, theses and dissertations, preprints, abstracts, technical reports, and other scholarly literature, including court opinions and patents.",
|
|
48
|
+
hackernews:
|
|
49
|
+
'Hacker News (HN) is an American social news website focusing on computer science and entrepreneurship. It is run by the investment fund and startup incubator Y Combinator. In general, content that can be submitted is defined as "anything that gratifies one\'s intellectual curiosity."',
|
|
50
|
+
imdb: "IMDb, historically known as the Internet Movie Database, is an online database of information related to films, television series, podcasts, video games, and streaming content online – including cast, production crew and biographies, plot summaries, trivia, ratings, and fan and critical reviews. As of September 2025, IMDb ranks as the 40th most visited website in the world and the 35th in the United States.",
|
|
51
|
+
imgur:
|
|
52
|
+
"Imgur is an American online image sharing community and image host founded by Alan Schaaf in 2009. The service has hosted viral images and memes, particularly those posted on Reddit.",
|
|
53
|
+
kickass:
|
|
54
|
+
"KickassTorrents was a website that provided a directory for torrent files and magnet links to facilitate peer-to-peer file sharing using the BitTorrent protocol. It was founded in 2008 and by November 2014, KAT became the most visited BitTorrent directory in the world, overtaking The Pirate Bay, according to the site's Alexa ranking. KAT went offline on 20 July 2016 when the domain was seized by the U.S. government. The site's proxy servers were shut down by its staff at the same time.",
|
|
55
|
+
mojeek:
|
|
56
|
+
"Mojeek is a UK-based search engine known for its focus on privacy and independence from other major search indexes. Established with a commitment to user privacy, Mojeek operates its own crawler-based index, setting it apart from search engines that rely on third-party search results, such as those from Google or Bing.",
|
|
57
|
+
npm: "npm is a package manager for the JavaScript programming language maintained by npm, Inc., a subsidiary of GitHub. npm is the default package manager for the JavaScript runtime environment Node.js and is included as a recommended feature in the Node.js installer.",
|
|
58
|
+
nyaa: "A BitTorrent community focused on Eastern Asian media including anime, manga, music, and more",
|
|
59
|
+
openlibrary:
|
|
60
|
+
'Open Library is an online project intended to create "one web page for every book ever published". Created by Aaron Swartz, Brewster Kahle, Alexis Rossi, Anand Chitipothu, and Rebecca Hargrave Malamud, Open Library is a project of the Internet Archive, a nonprofit organization. It has been funded in part by grants from the California State Library and the Kahle/Austin Foundation. Open Library provides online digital copies in multiple formats, created from images of many public domain, out-...',
|
|
61
|
+
openstreetmap:
|
|
62
|
+
"OpenStreetMap (OSM) is a map database maintained by a community of volunteers via open collaboration. Contributors collect data from surveys, trace from aerial photo imagery or satellite imagery, and import from other freely licensed geodata sources. OpenStreetMap is freely licensed under the Open Database License and is commonly used to make electronic maps, inform turn-by-turn navigation, and assist in humanitarian aid and data visualisation. OpenStreetMap uses its own data model to store g...",
|
|
63
|
+
packagist:
|
|
64
|
+
"The main Composer repository, aggregating public PHP packages installable with Composer",
|
|
65
|
+
peertube:
|
|
66
|
+
"PeerTube is a free and open-source, decentralized, ActivityPub federated video platform. It can use peer-to-peer technology to reduce load on individual servers when videos get popular.",
|
|
67
|
+
photon: "Photon, search-as-you-type with OpenStreetMap",
|
|
68
|
+
pixabay:
|
|
69
|
+
"Pixabay.com is a free stock photography and royalty-free stock media website. It is used for sharing photos, illustrations, vector graphics, film footage, stock music and sound effects, exclusively under the custom Pixabay Content License, which generally allows the free use of the material with some restrictions. The site's images are allowed to be used for free without attribution, and allowed to be modified and adapted into new works. Pixabay does not allow users to sell or distribute the ...",
|
|
70
|
+
pubmed:
|
|
71
|
+
"MEDLINE is a bibliographic database of life sciences and biomedical information. It includes bibliographic information for articles from academic journals covering medicine, nursing, pharmacy, dentistry, veterinary medicine, and health care. MEDLINE also covers much of the literature in biology and biochemistry, as well as fields such as molecular evolution.",
|
|
72
|
+
pypi: "The Python Package Index, abbreviated as PyPI and also known as the Cheese Shop, is the official third-party software repository for Python. It is analogous to the CPAN repository for Perl and to the CRAN repository for R. PyPI is run by the Python Software Foundation, a charity. Some package managers, including pip, use PyPI as the default source for packages and their dependencies.",
|
|
73
|
+
qwant:
|
|
74
|
+
"Qwant is a French search engine, launched in February 2013. Qwant says that it is focused on privacy, does not track users, resell personal data, or bias the display of search results. Its results are similar to the Microsoft Bing search engine however it is used only in case Qwant lacks information of certain website and for image searches. Qwant is currently only available in around 30 countries.",
|
|
75
|
+
reddit:
|
|
76
|
+
'Reddit is an American proprietary social news aggregation and forum social media platform. Registered users submit content to the site such as links, text posts, images, and videos, which are then voted up or down by other members. Posts are organized by subject into user-created boards called "subreddits". Submissions with more upvotes appear towards the top of their subreddit and, if they receive enough upvotes, ultimately on the site\'s front page. Reddit administrators moderate the commu...',
|
|
77
|
+
rubygems:
|
|
78
|
+
"RubyGems is a package manager for the Ruby programming language that provides a standard format for distributing Ruby programs and libraries, a tool designed to easily manage the installation of gems, and a server for distributing them. It was created by Chad Fowler, Jim Weirich, David Alan Black, Paul Brannan and Richard Kilmer in 2004.",
|
|
79
|
+
semantic_scholar:
|
|
80
|
+
"Semantic Scholar is a research tool for scientific literature. It is developed at the Allen Institute for AI and was publicly released in November 2015. Semantic Scholar uses modern techniques in natural language processing to support the research process, for example by providing automatically generated summaries of scholarly papers. The Semantic Scholar team is actively researching the use of artificial intelligence in natural language processing, machine learning, human–computer interactio...",
|
|
81
|
+
soundcloud:
|
|
82
|
+
"SoundCloud is a German audio streaming service owned and operated by SoundCloud Global Limited & Co. KG. The service allows its users to upload, promote, and share audio. Founded in 2007 by Alexander Ljung and Eric Wahlforss, SoundCloud is one of the largest music streaming services in the world and is available in 190 countries and territories. The service has upwards of 76 million active monthly users and over 200 million audio tracks as of November 2021. SoundCloud offers both free and pai...",
|
|
83
|
+
stackoverflow:
|
|
84
|
+
"Stack Exchange is a network of question-and-answer (Q&A) websites on topics in diverse fields, each site covering a specific topic, where questions, answers, and users are subject to a reputation award process. The reputation system allows the sites to be self-moderating. Currently, Stack Exchange is composed of 173 communities bringing in over 100 million unique visitors each month. As of February 2025 the three most active sites in the network were Stack Overflow, Mathematics, and Ask Ubuntu.",
|
|
85
|
+
startpage:
|
|
86
|
+
"Startpage.com is a Dutch search engine website that highlights privacy as its distinguishing feature. The website advertises that it allows users to obtain Bing Search and Google Search results while protecting users' privacy by not storing personal information or search data and removing all trackers. Startpage.com also includes an Anonymous View browsing feature that allows users the option to open search results via proxy for increased anonymity. Startpage is owned and operated by Surfboar...",
|
|
87
|
+
thepiratebay:
|
|
88
|
+
"The Pirate Bay, commonly abbreviated as TPB, is a free searchable online index of movies, music, video games, pornography and software. Founded in 2003 by Swedish think tank Piratbyrån, The Pirate Bay facilitates the connection among users of the peer-to-peer torrent protocol, which are able to contribute to the site through the addition of magnet links. The Pirate Bay has consistently ranked as one of the most visited torrent websites in the world.",
|
|
89
|
+
unsplash:
|
|
90
|
+
"Unsplash is a website dedicated to proprietary stock photography. Since 2021, it has been owned by Getty Images. The website claims over 330,000 contributing photographers and generates more than 13 billion photo impressions per month on their growing library of over 5 million photos. Unsplash has been cited as one of the world's leading photography websites by Forbes, Design Hub, CNET, Medium and The Next Web.",
|
|
91
|
+
vimeo:
|
|
92
|
+
"Vimeo is an American video hosting, sharing, and services provider founded in 2004 and headquartered in New York City. Vimeo focuses on the delivery of high-definition video across a range of devices and operates on a software as a service (SaaS) business model. The platform provides tools for video creation, editing, and broadcasting along with enterprise software solutions and the means for video professionals to connect with clients and other professionals. As of December 2021, the site ha...",
|
|
93
|
+
wallhaven: "Your source for the best high quality wallpapers on the Net!",
|
|
94
|
+
wikidata:
|
|
95
|
+
"Wikidata is a collaboratively edited multilingual knowledge graph hosted by the Wikimedia Foundation. It is a common source of open data that Wikimedia projects such as Wikipedia, and anyone else, are able to use under the CC0 public domain license. Wikidata is a wiki powered by the software MediaWiki, including its extension for semi-structured data, the Wikibase. As of early 2025, Wikidata had 1.65 billion item statements.",
|
|
96
|
+
wikipedia:
|
|
97
|
+
"Wikipedia is a free online encyclopedia written and maintained by a community of volunteers, usually known as Wikipedians, through open collaboration and the wiki software MediaWiki. Founded by Jimmy Wales and Larry Sanger in 2001, Wikipedia has been hosted since 2003 by the Wikimedia Foundation, an American nonprofit organization funded mainly by donations from readers. Wikipedia is the largest and most-read reference work in history.",
|
|
98
|
+
wttr: "weather forecast service",
|
|
99
|
+
yahoo:
|
|
100
|
+
"The search engine that helps you find exactly what you're looking for. Find the most relevant information, video, images, and answers from all across the Web.",
|
|
101
|
+
yahoo_news:
|
|
102
|
+
"Yahoo News is a news website that originated as an internet-based news aggregator by Yahoo.",
|
|
103
|
+
yandex:
|
|
104
|
+
"Yandex LLC is a Russian technology company that provides Internet-related products and services including a web browser, search engine, cloud computing, web mapping, online food ordering, streaming media, online shopping, and a ridesharing company.",
|
|
105
|
+
youtube:
|
|
106
|
+
"YouTube is an American social media and online video sharing platform owned by Google. YouTube was founded on February 14, 2005, by Chad Hurley, Jawed Karim, and Steve Chen, who were former employees of PayPal. Headquartered in San Bruno, California, it is the second-most-visited website in the world, after Google. In January 2024, YouTube had more than 2.7 billion monthly active users, who collectively watched more than one billion hours of videos every day. As of May 2019, videos were being...",
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Get the description for a named engine. Returns `undefined` if not found.
|
|
111
|
+
*/
|
|
112
|
+
export function getEngineDescription(engineName: string): string | undefined {
|
|
113
|
+
return engineDescriptions[engineName];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get the list of engine names that have a description entry.
|
|
118
|
+
*/
|
|
119
|
+
export function getEnginesWithDescriptions(): string[] {
|
|
120
|
+
return Object.keys(engineDescriptions);
|
|
121
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search Engine Status Tracker — Monitors the health of every search engine
|
|
3
|
+
* adapter at runtime. It records success and failure events, computes running
|
|
4
|
+
* failure rates, and automatically marks an engine as "failed" when more than
|
|
5
|
+
* 70 % of its recent requests have errored. Engines recover automatically once
|
|
6
|
+
* their success rate exceeds twice their failure count.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { EngineStatus, EngineLog } from "../types/search-result-types.js";
|
|
10
|
+
|
|
11
|
+
export class EngineStatusTracker {
|
|
12
|
+
private statusMap: Map<string, EngineStatus> = new Map();
|
|
13
|
+
private logs: EngineLog[] = [];
|
|
14
|
+
private maxLogs: number = 1000;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Initialise tracking state for an engine (no-op if already initialised).
|
|
18
|
+
*/
|
|
19
|
+
initEngine(name: string, categories: string[] = []): void {
|
|
20
|
+
if (!this.statusMap.has(name)) {
|
|
21
|
+
this.statusMap.set(name, {
|
|
22
|
+
name,
|
|
23
|
+
status: "active",
|
|
24
|
+
lastCheck: new Date(),
|
|
25
|
+
lastSuccess: null,
|
|
26
|
+
lastFailure: null,
|
|
27
|
+
failureCount: 0,
|
|
28
|
+
successCount: 0,
|
|
29
|
+
totalRequests: 0,
|
|
30
|
+
averageResponseTime: 0,
|
|
31
|
+
categories,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Record a successful engine execution and update rolling averages.
|
|
38
|
+
*/
|
|
39
|
+
recordSuccess(
|
|
40
|
+
engineName: string,
|
|
41
|
+
responseTime: number,
|
|
42
|
+
query?: string,
|
|
43
|
+
): void {
|
|
44
|
+
const status = this.statusMap.get(engineName);
|
|
45
|
+
if (!status) {
|
|
46
|
+
this.initEngine(engineName);
|
|
47
|
+
return this.recordSuccess(engineName, responseTime, query);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const now = new Date();
|
|
51
|
+
status.lastCheck = now;
|
|
52
|
+
status.lastSuccess = now;
|
|
53
|
+
status.successCount++;
|
|
54
|
+
status.totalRequests++;
|
|
55
|
+
|
|
56
|
+
const totalTime =
|
|
57
|
+
status.averageResponseTime * (status.successCount - 1) + responseTime;
|
|
58
|
+
status.averageResponseTime = totalTime / status.successCount;
|
|
59
|
+
|
|
60
|
+
if (status.failureCount > 0 && status.successCount > status.failureCount * 2) {
|
|
61
|
+
status.status = "active";
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
this.addLog({ timestamp: now, engineName, status: "success", responseTime, query });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Record a failed engine execution and escalate status if failure rate exceeds 70 %.
|
|
69
|
+
*/
|
|
70
|
+
recordFailure(
|
|
71
|
+
engineName: string,
|
|
72
|
+
error: string,
|
|
73
|
+
responseTime: number = 0,
|
|
74
|
+
query?: string,
|
|
75
|
+
): void {
|
|
76
|
+
const status = this.statusMap.get(engineName);
|
|
77
|
+
if (!status) {
|
|
78
|
+
this.initEngine(engineName);
|
|
79
|
+
return this.recordFailure(engineName, error, responseTime, query);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const now = new Date();
|
|
83
|
+
status.lastCheck = now;
|
|
84
|
+
status.lastFailure = now;
|
|
85
|
+
status.failureCount++;
|
|
86
|
+
status.totalRequests++;
|
|
87
|
+
status.lastError = error;
|
|
88
|
+
|
|
89
|
+
if (status.totalRequests >= 5) {
|
|
90
|
+
const failureRate = status.failureCount / status.totalRequests;
|
|
91
|
+
if (failureRate > 0.7) {
|
|
92
|
+
status.status = "failed";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this.addLog({
|
|
97
|
+
timestamp: now,
|
|
98
|
+
engineName,
|
|
99
|
+
status: "failure",
|
|
100
|
+
responseTime,
|
|
101
|
+
error,
|
|
102
|
+
query,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get the current status record for a specific engine.
|
|
108
|
+
*/
|
|
109
|
+
getStatus(engineName: string): EngineStatus | undefined {
|
|
110
|
+
return this.statusMap.get(engineName);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get status records for all tracked engines.
|
|
115
|
+
*/
|
|
116
|
+
getAllStatuses(): EngineStatus[] {
|
|
117
|
+
return Array.from(this.statusMap.values());
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Get status records filtered to a specific category.
|
|
122
|
+
*/
|
|
123
|
+
getStatusesByCategory(category: string): EngineStatus[] {
|
|
124
|
+
return Array.from(this.statusMap.values()).filter((status) =>
|
|
125
|
+
status.categories.includes(category),
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get the most recent log entries (default: last 100).
|
|
131
|
+
*/
|
|
132
|
+
getRecentLogs(limit: number = 100): EngineLog[] {
|
|
133
|
+
return this.logs.slice(-limit);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Get log entries for a specific engine (default: last 50).
|
|
138
|
+
*/
|
|
139
|
+
getEngineLogs(engineName: string, limit: number = 50): EngineLog[] {
|
|
140
|
+
return this.logs.filter((log) => log.engineName === engineName).slice(-limit);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Return the failure rate (0–1) for an engine. Returns 0 for unknown engines.
|
|
145
|
+
*/
|
|
146
|
+
getFailureRate(engineName: string): number {
|
|
147
|
+
const status = this.statusMap.get(engineName);
|
|
148
|
+
if (!status || status.totalRequests === 0) return 0;
|
|
149
|
+
return status.failureCount / status.totalRequests;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Return true if the engine is active (not failed or disabled).
|
|
154
|
+
* Unknown engines are assumed healthy.
|
|
155
|
+
*/
|
|
156
|
+
isEngineHealthy(engineName: string): boolean {
|
|
157
|
+
const status = this.statusMap.get(engineName);
|
|
158
|
+
if (!status) return true;
|
|
159
|
+
return status.status === "active";
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Manually disable an engine so it is skipped during searches.
|
|
164
|
+
*/
|
|
165
|
+
disableEngine(engineName: string): void {
|
|
166
|
+
const status = this.statusMap.get(engineName);
|
|
167
|
+
if (status) status.status = "disabled";
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Manually re-enable an engine and reset its failure count.
|
|
172
|
+
*/
|
|
173
|
+
enableEngine(engineName: string): void {
|
|
174
|
+
const status = this.statusMap.get(engineName);
|
|
175
|
+
if (status) {
|
|
176
|
+
status.status = "active";
|
|
177
|
+
status.failureCount = 0;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Reset all counters and status for an engine back to a clean active state.
|
|
183
|
+
*/
|
|
184
|
+
resetEngine(engineName: string): void {
|
|
185
|
+
const status = this.statusMap.get(engineName);
|
|
186
|
+
if (status) {
|
|
187
|
+
status.failureCount = 0;
|
|
188
|
+
status.successCount = 0;
|
|
189
|
+
status.totalRequests = 0;
|
|
190
|
+
status.averageResponseTime = 0;
|
|
191
|
+
status.status = "active";
|
|
192
|
+
status.lastError = undefined;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Clear all stored log entries.
|
|
198
|
+
*/
|
|
199
|
+
clearLogs(): void {
|
|
200
|
+
this.logs = [];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Get a high-level summary of engine health across all tracked engines.
|
|
205
|
+
*/
|
|
206
|
+
getStatsSummary(): {
|
|
207
|
+
total: number;
|
|
208
|
+
active: number;
|
|
209
|
+
failed: number;
|
|
210
|
+
disabled: number;
|
|
211
|
+
averageFailureRate: number;
|
|
212
|
+
} {
|
|
213
|
+
const statuses = this.getAllStatuses();
|
|
214
|
+
const total = statuses.length;
|
|
215
|
+
const active = statuses.filter((s) => s.status === "active").length;
|
|
216
|
+
const failed = statuses.filter((s) => s.status === "failed").length;
|
|
217
|
+
const disabled = statuses.filter((s) => s.status === "disabled").length;
|
|
218
|
+
|
|
219
|
+
const failureRates = statuses
|
|
220
|
+
.filter((s) => s.totalRequests > 0)
|
|
221
|
+
.map((s) => s.failureCount / s.totalRequests);
|
|
222
|
+
|
|
223
|
+
const averageFailureRate =
|
|
224
|
+
failureRates.length > 0
|
|
225
|
+
? failureRates.reduce((a, b) => a + b, 0) / failureRates.length
|
|
226
|
+
: 0;
|
|
227
|
+
|
|
228
|
+
return { total, active, failed, disabled, averageFailureRate };
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private addLog(log: EngineLog): void {
|
|
232
|
+
this.logs.push(log);
|
|
233
|
+
if (this.logs.length > this.maxLogs) {
|
|
234
|
+
this.logs = this.logs.slice(-this.maxLogs);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Global singleton instance used throughout the application. */
|
|
240
|
+
export const engineStatusTracker = new EngineStatusTracker();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Result Container — Re-exports the ResultContainer class from its canonical
|
|
3
|
+
* location in the search module. ResultContainer aggregates results from multiple
|
|
4
|
+
* engines, deduplicates by URL hash, merges duplicate records, scores results
|
|
5
|
+
* using position-weighted per-engine and per-category multipliers, and groups
|
|
6
|
+
* the final list by result category.
|
|
7
|
+
*/
|
|
8
|
+
export * from "./search/search-result-container.js";
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Search Engines Registry List — Defines the complete catalogue of all 75 search
|
|
3
|
+
* engine adapters available in this package, organised by category. Each entry
|
|
4
|
+
* maps an engine name to its async query function and one or more categories.
|
|
5
|
+
* Also sets the global grab-url default User-Agent header so every engine
|
|
6
|
+
* request appears as a standard browser request.
|
|
7
|
+
*
|
|
8
|
+
* Split from the main search module to keep the large import block and static
|
|
9
|
+
* data separate from the query-execution logic.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { EngineFunction } from "../types/search-engine-interface.js";
|
|
13
|
+
import { EngineMetadata } from "../types/search-result-types.js";
|
|
14
|
+
import { engineDescriptions } from "../registry/search-engine-descriptions.js";
|
|
15
|
+
import grab from "grab-url";
|
|
16
|
+
|
|
17
|
+
// Set default browser User-Agent for all outgoing requests
|
|
18
|
+
grab("", {
|
|
19
|
+
setDefaults: true,
|
|
20
|
+
headers: {
|
|
21
|
+
"User-Agent":
|
|
22
|
+
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// General search engines
|
|
27
|
+
import { google } from "../sources/general/google.js";
|
|
28
|
+
import { bing } from "../sources/general/bing.js";
|
|
29
|
+
import { duckduckgo } from "../sources/general/duckduckgo.js";
|
|
30
|
+
import { yahoo } from "../sources/general/yahoo.js";
|
|
31
|
+
import { qwant } from "../sources/general/qwant.js";
|
|
32
|
+
import { startpage } from "../sources/general/startpage.js";
|
|
33
|
+
import { brave } from "../sources/general/brave.js";
|
|
34
|
+
import { yandex } from "../sources/general/yandex.js";
|
|
35
|
+
import { baidu } from "../sources/general/baidu.js";
|
|
36
|
+
import { mojeek } from "../sources/general/mojeek.js";
|
|
37
|
+
|
|
38
|
+
// IT / Developer engines
|
|
39
|
+
import { github } from "../sources/it/github.js";
|
|
40
|
+
import { stackoverflow } from "../sources/it/stackoverflow.js";
|
|
41
|
+
import { npm } from "../sources/it/npm.js";
|
|
42
|
+
import { crates } from "../sources/it/crates.js";
|
|
43
|
+
import { dockerhub } from "../sources/it/dockerhub.js";
|
|
44
|
+
import { pypi } from "../sources/it/pypi.js";
|
|
45
|
+
import { packagist } from "../sources/it/packagist.js";
|
|
46
|
+
import { rubygems } from "../sources/it/rubygems.js";
|
|
47
|
+
import { gitlab } from "../sources/it/gitlab.js";
|
|
48
|
+
|
|
49
|
+
// Image engines
|
|
50
|
+
import { unsplash } from "../sources/images/unsplash.js";
|
|
51
|
+
import { bing_images } from "../sources/images/bing_images.js";
|
|
52
|
+
import { google_images } from "../sources/images/google_images.js";
|
|
53
|
+
import { flickr } from "../sources/images/flickr.js";
|
|
54
|
+
import { imgur } from "../sources/images/imgur.js";
|
|
55
|
+
import { pixabay } from "../sources/images/pixabay.js";
|
|
56
|
+
import { wallhaven } from "../sources/images/wallhaven.js";
|
|
57
|
+
import { deviantart } from "../sources/images/deviantart.js";
|
|
58
|
+
import { openclipart } from "../sources/images/openclipart.js";
|
|
59
|
+
|
|
60
|
+
// Video engines
|
|
61
|
+
import { youtube } from "../sources/videos/youtube.js";
|
|
62
|
+
import { vimeo } from "../sources/videos/vimeo.js";
|
|
63
|
+
import { dailymotion } from "../sources/videos/dailymotion.js";
|
|
64
|
+
import { invidious } from "../sources/videos/invidious.js";
|
|
65
|
+
import { peertube } from "../sources/videos/peertube.js";
|
|
66
|
+
import { bing_videos } from "../sources/videos/bing_videos.js";
|
|
67
|
+
|
|
68
|
+
// News engines
|
|
69
|
+
import { hackernews } from "../sources/news/hackernews.js";
|
|
70
|
+
import { yahoo_news } from "../sources/news/yahoo_news.js";
|
|
71
|
+
import { bing_news } from "../sources/news/bing_news.js";
|
|
72
|
+
import { google_news } from "../sources/news/google_news.js";
|
|
73
|
+
|
|
74
|
+
// Academic engines
|
|
75
|
+
import { google_scholar } from "../sources/academic/google_scholar.js";
|
|
76
|
+
import { arxiv } from "../sources/academic/arxiv.js";
|
|
77
|
+
import { wikidata } from "../sources/academic/wikidata.js";
|
|
78
|
+
import { semantic_scholar } from "../sources/academic/semantic_scholar.js";
|
|
79
|
+
import { crossref } from "../sources/academic/crossref.js";
|
|
80
|
+
import { pubmed } from "../sources/academic/pubmed.js";
|
|
81
|
+
import { openalex } from "../sources/academic/openalex.js";
|
|
82
|
+
import { doaj } from "../sources/academic/doaj.js";
|
|
83
|
+
import { core } from "../sources/academic/core.js";
|
|
84
|
+
|
|
85
|
+
// Torrent engines
|
|
86
|
+
import { torrent_1337x } from "../sources/torrents/1337x.js";
|
|
87
|
+
import { thepiratebay } from "../sources/torrents/thepiratebay.js";
|
|
88
|
+
import { nyaa } from "../sources/torrents/nyaa.js";
|
|
89
|
+
import { yts } from "../sources/torrents/yts.js";
|
|
90
|
+
import { eztv } from "../sources/torrents/eztv.js";
|
|
91
|
+
import { solidtorrents } from "../sources/torrents/solidtorrents.js";
|
|
92
|
+
import { kickass } from "../sources/torrents/kickass.js";
|
|
93
|
+
|
|
94
|
+
// Social media engines
|
|
95
|
+
import { twitter } from "../sources/social/twitter.js";
|
|
96
|
+
import { reddit } from "../sources/social/reddit.js";
|
|
97
|
+
import { medium } from "../sources/social/medium.js";
|
|
98
|
+
import { soundcloud } from "../sources/social/soundcloud.js";
|
|
99
|
+
import { mastodon } from "../sources/social/mastodon.js";
|
|
100
|
+
|
|
101
|
+
// Map engines
|
|
102
|
+
import { openstreetmap } from "../sources/maps/openstreetmap.js";
|
|
103
|
+
import { photon } from "../sources/maps/photon.js";
|
|
104
|
+
import { apple_maps } from "../sources/maps/apple_maps.js";
|
|
105
|
+
|
|
106
|
+
// Shopping engines
|
|
107
|
+
import { ebay } from "../sources/shopping/ebay.js";
|
|
108
|
+
|
|
109
|
+
// Specialised engines
|
|
110
|
+
import { wikipedia } from "../sources/specialized/wikipedia.js";
|
|
111
|
+
import { imdb } from "../sources/specialized/imdb.js";
|
|
112
|
+
import { genius } from "../sources/specialized/genius.js";
|
|
113
|
+
import { archive } from "../sources/specialized/archive.js";
|
|
114
|
+
import { openlibrary } from "../sources/specialized/openlibrary.js";
|
|
115
|
+
import { wttr } from "../sources/specialized/wttr.js";
|
|
116
|
+
import { annas_archive } from "../sources/specialized/annas_archive.js";
|
|
117
|
+
import { goodreads } from "../sources/specialized/goodreads.js";
|
|
118
|
+
|
|
119
|
+
export { engineDescriptions };
|
|
120
|
+
|
|
121
|
+
/** Complete list of all 75 registered search engine adapters. */
|
|
122
|
+
export const ALL_ENGINES: EngineMetadata[] = [
|
|
123
|
+
// General (10)
|
|
124
|
+
{ name: "google", fn: google, categories: ["general"] },
|
|
125
|
+
{ name: "bing", fn: bing, categories: ["general"] },
|
|
126
|
+
{ name: "duckduckgo", fn: duckduckgo, categories: ["general"] },
|
|
127
|
+
{ name: "yahoo", fn: yahoo, categories: ["general"] },
|
|
128
|
+
{ name: "qwant", fn: qwant, categories: ["general"] },
|
|
129
|
+
{ name: "startpage", fn: startpage, categories: ["general"] },
|
|
130
|
+
{ name: "brave", fn: brave, categories: ["general"] },
|
|
131
|
+
{ name: "yandex", fn: yandex, categories: ["general"] },
|
|
132
|
+
{ name: "baidu", fn: baidu, categories: ["general"] },
|
|
133
|
+
{ name: "mojeek", fn: mojeek, categories: ["general"] },
|
|
134
|
+
// IT / Developer (9)
|
|
135
|
+
{ name: "github", fn: github, categories: ["it"] },
|
|
136
|
+
{ name: "gitlab", fn: gitlab, categories: ["it"] },
|
|
137
|
+
{ name: "stackoverflow", fn: stackoverflow, categories: ["it"] },
|
|
138
|
+
{ name: "npm", fn: npm, categories: ["it"] },
|
|
139
|
+
{ name: "crates", fn: crates, categories: ["it"] },
|
|
140
|
+
{ name: "dockerhub", fn: dockerhub, categories: ["it"] },
|
|
141
|
+
{ name: "pypi", fn: pypi, categories: ["it"] },
|
|
142
|
+
{ name: "packagist", fn: packagist, categories: ["it"] },
|
|
143
|
+
{ name: "rubygems", fn: rubygems, categories: ["it"] },
|
|
144
|
+
// Images (9)
|
|
145
|
+
{ name: "unsplash", fn: unsplash, categories: ["images"] },
|
|
146
|
+
{ name: "bing_images", fn: bing_images, categories: ["images"] },
|
|
147
|
+
{ name: "google_images", fn: google_images, categories: ["images"] },
|
|
148
|
+
{ name: "flickr", fn: flickr, categories: ["images"] },
|
|
149
|
+
{ name: "imgur", fn: imgur, categories: ["images"] },
|
|
150
|
+
{ name: "pixabay", fn: pixabay, categories: ["images"] },
|
|
151
|
+
{ name: "wallhaven", fn: wallhaven, categories: ["images"] },
|
|
152
|
+
{ name: "deviantart", fn: deviantart, categories: ["images"] },
|
|
153
|
+
{ name: "openclipart", fn: openclipart, categories: ["images"] },
|
|
154
|
+
// Videos (6)
|
|
155
|
+
{ name: "youtube", fn: youtube, categories: ["videos"] },
|
|
156
|
+
{ name: "vimeo", fn: vimeo, categories: ["videos"] },
|
|
157
|
+
{ name: "dailymotion", fn: dailymotion, categories: ["videos"] },
|
|
158
|
+
{ name: "bing_videos", fn: bing_videos, categories: ["videos"] },
|
|
159
|
+
{ name: "invidious", fn: invidious, categories: ["videos"] },
|
|
160
|
+
{ name: "peertube", fn: peertube, categories: ["videos"] },
|
|
161
|
+
// News (4)
|
|
162
|
+
{ name: "hackernews", fn: hackernews, categories: ["news"] },
|
|
163
|
+
{ name: "yahoo_news", fn: yahoo_news, categories: ["news"] },
|
|
164
|
+
{ name: "bing_news", fn: bing_news, categories: ["news"] },
|
|
165
|
+
{ name: "google_news", fn: google_news, categories: ["news"] },
|
|
166
|
+
// Academic (9)
|
|
167
|
+
{ name: "google_scholar", fn: google_scholar, categories: ["academic"] },
|
|
168
|
+
{ name: "arxiv", fn: arxiv, categories: ["academic"] },
|
|
169
|
+
{ name: "wikidata", fn: wikidata, categories: ["academic"] },
|
|
170
|
+
{ name: "semantic_scholar", fn: semantic_scholar, categories: ["academic"] },
|
|
171
|
+
{ name: "crossref", fn: crossref, categories: ["academic"] },
|
|
172
|
+
{ name: "pubmed", fn: pubmed, categories: ["academic"] },
|
|
173
|
+
{ name: "openalex", fn: openalex, categories: ["academic"] },
|
|
174
|
+
{ name: "doaj", fn: doaj, categories: ["academic"] },
|
|
175
|
+
{ name: "core", fn: core, categories: ["academic"] },
|
|
176
|
+
// Torrents (7)
|
|
177
|
+
{ name: "1337x", fn: torrent_1337x, categories: ["torrents"] },
|
|
178
|
+
{ name: "thepiratebay", fn: thepiratebay, categories: ["torrents"] },
|
|
179
|
+
{ name: "nyaa", fn: nyaa, categories: ["torrents"] },
|
|
180
|
+
{ name: "yts", fn: yts, categories: ["torrents"] },
|
|
181
|
+
{ name: "eztv", fn: eztv, categories: ["torrents"] },
|
|
182
|
+
{ name: "solidtorrents", fn: solidtorrents, categories: ["torrents"] },
|
|
183
|
+
{ name: "kickass", fn: kickass, categories: ["torrents"] },
|
|
184
|
+
// Social (5)
|
|
185
|
+
{ name: "twitter", fn: twitter, categories: ["social"] },
|
|
186
|
+
{ name: "reddit", fn: reddit, categories: ["social"] },
|
|
187
|
+
{ name: "medium", fn: medium, categories: ["social"] },
|
|
188
|
+
{ name: "soundcloud", fn: soundcloud, categories: ["social"] },
|
|
189
|
+
{ name: "mastodon", fn: mastodon, categories: ["social"] },
|
|
190
|
+
// Maps (3)
|
|
191
|
+
{ name: "openstreetmap", fn: openstreetmap, categories: ["maps"] },
|
|
192
|
+
{ name: "photon", fn: photon, categories: ["maps"] },
|
|
193
|
+
{ name: "apple_maps", fn: apple_maps, categories: ["maps"] },
|
|
194
|
+
// Shopping (1)
|
|
195
|
+
{ name: "ebay", fn: ebay, categories: ["shopping"] },
|
|
196
|
+
// Specialised (8)
|
|
197
|
+
{ name: "wikipedia", fn: wikipedia, categories: ["specialized"] },
|
|
198
|
+
{ name: "imdb", fn: imdb, categories: ["specialized"] },
|
|
199
|
+
{ name: "genius", fn: genius, categories: ["specialized"] },
|
|
200
|
+
{ name: "archive", fn: archive, categories: ["specialized"] },
|
|
201
|
+
{ name: "openlibrary", fn: openlibrary, categories: ["specialized"] },
|
|
202
|
+
{ name: "wttr", fn: wttr, categories: ["specialized"] },
|
|
203
|
+
{ name: "annas_archive", fn: annas_archive, categories: ["specialized"] },
|
|
204
|
+
{ name: "goodreads", fn: goodreads, categories: ["specialized"] },
|
|
205
|
+
];
|