123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- <?php
- /**
- * This class implements a bridge for http://www.instructables.com, supporting
- * general feeds and feeds by category. Instructables doesn't support HTTPS as
- * of now (23.06.2018), so all connections are insecure!
- *
- * Remarks:
- * - For some reason it is very important to have the category URI end with a
- * slash, otherwise the site defaults to the main category (i.e. Technology)!
- * If you need to update the categories list, enable the 'listCategories'
- * function (see comments below) and run the bridge with format=Html (see page
- * source)
- */
- class InstructablesBridge extends BridgeAbstract {
- const NAME = 'Instructables Bridge';
- const URI = 'http://www.instructables.com';
- const DESCRIPTION = 'Returns general feeds and feeds by category';
- const MAINTAINER = 'logmanoriginal';
- const PARAMETERS = array(
- 'Category' => array(
- 'category' => array(
- 'name' => 'Category',
- 'type' => 'list',
- 'required' => true,
- 'values' => array(
- 'Play' => array(
- 'All' => '/play/',
- 'KNEX' => '/play/knex/',
- 'Offbeat' => '/play/offbeat/',
- 'Lego' => '/play/lego/',
- 'Airsoft' => '/play/airsoft/',
- 'Card Games' => '/play/card-games/',
- 'Guitars' => '/play/guitars/',
- 'Instruments' => '/play/instruments/',
- 'Magic Tricks' => '/play/magic-tricks/',
- 'Minecraft' => '/play/minecraft/',
- 'Music' => '/play/music/',
- 'Nerf' => '/play/nerf/',
- 'Nintendo' => '/play/nintendo/',
- 'Office Supplies' => '/play/office-supplies/',
- 'Paintball' => '/play/paintball/',
- 'Paper Airplanes' => '/play/paper-airplanes/',
- 'Party Tricks' => '/play/party-tricks/',
- 'PlayStation' => '/play/playstation/',
- 'Pranks and Humor' => '/play/pranks-and-humor/',
- 'Puzzles' => '/play/puzzles/',
- 'Siege Engines' => '/play/siege-engines/',
- 'Sports' => '/play/sports/',
- 'Table Top' => '/play/table-top/',
- 'Toys' => '/play/toys/',
- 'Video Games' => '/play/video-games/',
- 'Wii' => '/play/wii/',
- 'Xbox' => '/play/xbox/',
- 'Yo-Yo' => '/play/yo-yo/',
- ),
- 'Craft' => array(
- 'All' => '/craft/',
- 'Art' => '/craft/art/',
- 'Sewing' => '/craft/sewing/',
- 'Paper' => '/craft/paper/',
- 'Jewelry' => '/craft/jewelry/',
- 'Fashion' => '/craft/fashion/',
- 'Books & Journals' => '/craft/books-and-journals/',
- 'Cards' => '/craft/cards/',
- 'Clay' => '/craft/clay/',
- 'Duct Tape' => '/craft/duct-tape/',
- 'Embroidery' => '/craft/embroidery/',
- 'Felt' => '/craft/felt/',
- 'Fiber Arts' => '/craft/fiber-arts/',
- 'Gifts & Wrapping' => '/craft/gifts-and-wrapping/',
- 'Knitting & Crocheting' => '/craft/knitting-and-crocheting/',
- 'Leather' => '/craft/leather/',
- 'Mason Jars' => '/craft/mason-jars/',
- 'No-Sew' => '/craft/no-sew/',
- 'Parties & Weddings' => '/craft/parties-and-weddings/',
- 'Print Making' => '/craft/print-making/',
- 'Soap' => '/craft/soap/',
- 'Wallets' => '/craft/wallets/',
- ),
- 'Technology' => array(
- 'All' => '/technology/',
- 'Electronics' => '/technology/electronics/',
- 'Arduino' => '/technology/arduino/',
- 'Photography' => '/technology/photography/',
- 'Leds' => '/technology/leds/',
- 'Science' => '/technology/science/',
- 'Reuse' => '/technology/reuse/',
- 'Apple' => '/technology/apple/',
- 'Computers' => '/technology/computers/',
- '3D Printing' => '/technology/3D-Printing/',
- 'Robots' => '/technology/robots/',
- 'Art' => '/technology/art/',
- 'Assistive Tech' => '/technology/assistive-technology/',
- 'Audio' => '/technology/audio/',
- 'Clocks' => '/technology/clocks/',
- 'CNC' => '/technology/cnc/',
- 'Digital Graphics' => '/technology/digital-graphics/',
- 'Gadgets' => '/technology/gadgets/',
- 'Kits' => '/technology/kits/',
- 'Laptops' => '/technology/laptops/',
- 'Lasers' => '/technology/lasers/',
- 'Linux' => '/technology/linux/',
- 'Microcontrollers' => '/technology/microcontrollers/',
- 'Microsoft' => '/technology/microsoft/',
- 'Mobile' => '/technology/mobile/',
- 'Raspberry Pi' => '/technology/raspberry-pi/',
- 'Remote Control' => '/technology/remote-control/',
- 'Sensors' => '/technology/sensors/',
- 'Software' => '/technology/software/',
- 'Soldering' => '/technology/soldering/',
- 'Speakers' => '/technology/speakers/',
- 'Steampunk' => '/technology/steampunk/',
- 'Tools' => '/technology/tools/',
- 'USB' => '/technology/usb/',
- 'Wearables' => '/technology/wearables/',
- 'Websites' => '/technology/websites/',
- 'Wireless' => '/technology/wireless/',
- ),
- 'Workshop' => array(
- 'All' => '/workshop/',
- 'Woodworking' => '/workshop/woodworking/',
- 'Tools' => '/workshop/tools/',
- 'Gardening' => '/workshop/gardening/',
- 'Cars' => '/workshop/cars/',
- 'Metalworking' => '/workshop/metalworking/',
- 'Cardboard' => '/workshop/cardboard/',
- 'Electric Vehicles' => '/workshop/electric-vehicles/',
- 'Energy' => '/workshop/energy/',
- 'Furniture' => '/workshop/furniture/',
- 'Home Improvement' => '/workshop/home-improvement/',
- 'Home Theater' => '/workshop/home-theater/',
- 'Hydroponics' => '/workshop/hydroponics/',
- 'Laser Cutting' => '/workshop/laser-cutting/',
- 'Lighting' => '/workshop/lighting/',
- 'Molds & Casting' => '/workshop/molds-and-casting/',
- 'Motorcycles' => '/workshop/motorcycles/',
- 'Organizing' => '/workshop/organizing/',
- 'Pallets' => '/workshop/pallets/',
- 'Repair' => '/workshop/repair/',
- 'Shelves' => '/workshop/shelves/',
- 'Solar' => '/workshop/solar/',
- 'Workbenches' => '/workshop/workbenches/',
- ),
- 'Home' => array(
- 'All' => '/home/',
- 'Halloween' => '/home/halloween/',
- 'Decorating' => '/home/decorating/',
- 'Organizing' => '/home/organizing/',
- 'Pets' => '/home/pets/',
- 'Life Hacks' => '/home/life-hacks/',
- 'Beauty' => '/home/beauty/',
- 'Christmas' => '/home/christmas/',
- 'Cleaning' => '/home/cleaning/',
- 'Education' => '/home/education/',
- 'Finances' => '/home/finances/',
- 'Gardening' => '/home/gardening/',
- 'Green' => '/home/green/',
- 'Health' => '/home/health/',
- 'Hiding Places' => '/home/hiding-places/',
- 'Holidays' => '/home/holidays/',
- 'Homesteading' => '/home/homesteading/',
- 'Kids' => '/home/kids/',
- 'Kitchen' => '/home/kitchen/',
- 'Life Skills' => '/home/life-skills/',
- 'Parenting' => '/home/parenting/',
- 'Pest Control' => '/home/pest-control/',
- 'Relationships' => '/home/relationships/',
- 'Reuse' => '/home/reuse/',
- 'Travel' => '/home/travel/',
- ),
- 'Outside' => array(
- 'All' => '/outside/',
- 'Bikes' => '/outside/bikes/',
- 'Survival' => '/outside/survival/',
- 'Backyard' => '/outside/backyard/',
- 'Beach' => '/outside/beach/',
- 'Birding' => '/outside/birding/',
- 'Boats' => '/outside/boats/',
- 'Camping' => '/outside/camping/',
- 'Climbing' => '/outside/climbing/',
- 'Fire' => '/outside/fire/',
- 'Fishing' => '/outside/fishing/',
- 'Hunting' => '/outside/hunting/',
- 'Kites' => '/outside/kites/',
- 'Knives' => '/outside/knives/',
- 'Knots' => '/outside/knots/',
- 'Paracord' => '/outside/paracord/',
- 'Rockets' => '/outside/rockets/',
- 'Skateboarding' => '/outside/skateboarding/',
- 'Snow' => '/outside/snow/',
- 'Water' => '/outside/water/',
- ),
- 'Food' => array(
- 'All' => '/food/',
- 'Dessert' => '/food/dessert/',
- 'Snacks & Appetizers' => '/food/snacks-and-appetizers/',
- 'Bacon' => '/food/bacon/',
- 'BBQ & Grilling' => '/food/bbq-and-grilling/',
- 'Beverages' => '/food/beverages/',
- 'Bread' => '/food/bread/',
- 'Breakfast' => '/food/breakfast/',
- 'Cake' => '/food/cake/',
- 'Candy' => '/food/candy/',
- 'Canning & Preserves' => '/food/canning-and-preserves/',
- 'Cocktails & Mocktails' => '/food/cocktails-and-mocktails/',
- 'Coffee' => '/food/coffee/',
- 'Cookies' => '/food/cookies/',
- 'Cupcakes' => '/food/cupcakes/',
- 'Homebrew' => '/food/homebrew/',
- 'Main Course' => '/food/main-course/',
- 'Pasta' => '/food/pasta/',
- 'Pie' => '/food/pie/',
- 'Pizza' => '/food/pizza/',
- 'Salad' => '/food/salad/',
- 'Sandwiches' => '/food/sandwiches/',
- 'Soups & Stews' => '/food/soups-and-stews/',
- 'Vegetarian & Vegan' => '/food/vegetarian-and-vegan/',
- ),
- 'Costumes' => array(
- 'All' => '/costumes/',
- 'Props' => '/costumes/props-and-accessories/',
- 'Animals' => '/costumes/animals/',
- 'Comics' => '/costumes/comics/',
- 'Fantasy' => '/costumes/fantasy/',
- 'For Kids' => '/costumes/for-kids/',
- 'For Pets' => '/costumes/for-pets/',
- 'Funny' => '/costumes/funny/',
- 'Games' => '/costumes/games/',
- 'Historic & Futuristic' => '/costumes/historic-and-futuristic/',
- 'Makeup' => '/costumes/makeup/',
- 'Masks' => '/costumes/masks/',
- 'Scary' => '/costumes/scary/',
- 'TV & Movies' => '/costumes/tv-and-movies/',
- 'Weapons & Armor' => '/costumes/weapons-and-armor/',
- )
- ),
- 'title' => 'Select your category (required)',
- 'defaultValue' => 'Technology'
- ),
- 'filter' => array(
- 'name' => 'Filter',
- 'type' => 'list',
- 'required' => true,
- 'values' => array(
- 'Featured' => ' ',
- 'Recent' => 'recent/',
- 'Popular' => 'popular/',
- 'Views' => 'views/',
- 'Contest Winners' => 'winners/'
- ),
- 'title' => 'Select a filter',
- 'defaultValue' => 'Featured'
- )
- )
- );
- private $uri;
- public function collectData() {
- // Enable the following line to get the category list (dev mode)
- // $this->listCategories();
- $this->uri = static::URI;
- switch($this->queriedContext) {
- case 'Category': $this->uri .= $this->getInput('category') . $this->getInput('filter');
- }
- $html = getSimpleHTMLDOM($this->uri)
- or returnServerError('Error loading category ' . $this->uri);
- foreach($html->find('ul.explore-covers-list li') as $cover) {
- $item = array();
- $item['uri'] = static::URI . $cover->find('a.cover-image', 0)->href;
- $item['title'] = $cover->find('.title', 0)->innertext;
- $item['author'] = $this->getCategoryAuthor($cover);
- $item['content'] = '<a href='
- . $item['uri']
- . '><img src='
- . $cover->find('a.cover-image img', 0)->src
- . '></a>';
- $image = str_replace('.RECTANGLE1', '.LARGE', $cover->find('a.cover-image img', 0)->src);
- $item['enclosures'] = [$image];
- $this->items[] = $item;
- }
- }
- public function getName() {
- if(!is_null($this->getInput('category'))
- && !is_null($this->getInput('filter'))) {
- foreach(self::PARAMETERS[$this->queriedContext]['category']['values'] as $key => $value) {
- $subcategory = array_search($this->getInput('category'), $value);
- if($subcategory !== false)
- break;
- }
- $filter = array_search(
- $this->getInput('filter'),
- self::PARAMETERS[$this->queriedContext]['filter']['values']
- );
- return $subcategory . ' (' . $filter . ') - ' . static::NAME;
- }
- return parent::getName();
- }
- public function getURI() {
- if(!is_null($this->getInput('category'))
- && !is_null($this->getInput('filter'))) {
- return $this->uri;
- }
- return parent::getURI();
- }
- /**
- * Returns a list of categories for development purposes (used to build the
- * parameters list)
- */
- private function listCategories(){
- // Use arbitrary category to receive full list
- $html = getSimpleHTMLDOM(self::URI . '/technology/');
- foreach($html->find('.channel a') as $channel) {
- $name = html_entity_decode(trim($channel->innertext));
- // Remove unwanted entities
- $name = str_replace("'", '', $name);
- $name = str_replace(''', '', $name);
- $uri = $channel->href;
- $category = explode('/', $uri)[1];
- if(!isset($categories)
- || !array_key_exists($category, $categories)
- || !in_array($uri, $categories[$category]))
- $categories[$category][$name] = $uri;
- }
- // Build PHP array manually
- foreach($categories as $key => $value) {
- $name = ucfirst($key);
- echo "'{$name}' => array(\n";
- echo "\t'All' => '/{$key}/',\n";
- foreach($value as $name => $uri) {
- echo "\t'{$name}' => '{$uri}',\n";
- }
- echo "),\n";
- }
- die;
- }
- /**
- * Returns the author as anchor for a given cover.
- */
- private function getCategoryAuthor($cover) {
- return '<a href='
- . static::URI . $cover->find('span.author a', 0)->href
- . '>'
- . $cover->find('span.author a', 0)->innertext
- . '</a>';
- }
- }
|