diff --git a/bridges/BadDragonBridge.php b/bridges/BadDragonBridge.php new file mode 100644 index 00000000..d606c4e1 --- /dev/null +++ b/bridges/BadDragonBridge.php @@ -0,0 +1,435 @@ + array( + ), + 'Clearance' => array( + 'ready_made' => array( + 'name' => 'Ready Made', + 'type' => 'checkbox' + ), + 'flop' => array( + 'name' => 'Flops', + 'type' => 'checkbox' + ), + 'skus' => array( + 'name' => 'Products', + 'exampleValue' => 'chanceflared, crackers', + 'title' => 'Comma separated list of product SKUs' + ), + 'onesize' => array( + 'name' => 'One-Size', + 'type' => 'checkbox' + ), + 'mini' => array( + 'name' => 'Mini', + 'type' => 'checkbox' + ), + 'small' => array( + 'name' => 'Small', + 'type' => 'checkbox' + ), + 'medium' => array( + 'name' => 'Medium', + 'type' => 'checkbox' + ), + 'large' => array( + 'name' => 'Large', + 'type' => 'checkbox' + ), + 'extralarge' => array( + 'name' => 'Extra Large', + 'type' => 'checkbox' + ), + 'category' => array( + 'name' => 'Category', + 'type' => 'list', + 'values' => array( + 'All' => 'all', + 'Accessories' => 'accessories', + 'Merchandise' => 'merchandise', + 'Dildos' => 'insertable', + 'Masturbators' => 'penetrable', + 'Packers' => 'packer', + 'Lil\' Squirts' => 'shooter', + 'Lil\' Vibes' => 'vibrator', + 'Wearables' => 'wearable' + ), + 'defaultValue' => 'all', + ), + 'soft' => array( + 'name' => 'Soft Firmness', + 'type' => 'checkbox' + ), + 'med_firm' => array( + 'name' => 'Medium Firmness', + 'type' => 'checkbox' + ), + 'firm' => array( + 'name' => 'Firm', + 'type' => 'checkbox' + ), + 'split' => array( + 'name' => 'Split Firmness', + 'type' => 'checkbox' + ), + 'maxprice' => array( + 'name' => 'Max Price', + 'type' => 'number', + 'required' => true, + 'defaultValue' => 300 + ), + 'minprice' => array( + 'name' => 'Min Price', + 'type' => 'number', + 'defaultValue' => 0 + ), + 'cumtube' => array( + 'name' => 'Cumtube', + 'type' => 'checkbox' + ), + 'suctionCup' => array( + 'name' => 'Suction Cup', + 'type' => 'checkbox' + ), + 'noAccessories' => array( + 'name' => 'No Accessories', + 'type' => 'checkbox' + ) + ) + ); + + /* + * This sets index $strFrom (or $strTo if set) in $outArr to 'on' if + * $inArr[$param] contains $strFrom. + * It is used for translating BD's shop filter URLs into something we can use. + * + * For the query '?type[]=ready_made&type[]=flop' we would have an array like: + * Array ( + * [type] => Array ( + * [0] => ready_made + * [1] => flop + * ) + * ) + * which could be translated into: + * Array ( + * [ready_made] => on + * [flop] => on + * ) + * */ + private function setParam($inArr, &$outArr, $param, $strFrom, $strTo = null) { + if(isset($inArr[$param]) && in_array($strFrom, $inArr[$param])) { + $outArr[($strTo ?: $strFrom)] = 'on'; + } + } + + public function detectParameters($url) { + $params = array(); + + // Sale + $regex = '/^(https?:\/\/)?bad-dragon\.com\/sales/'; + if(preg_match($regex, $url, $matches) > 0) { + return $params; + } + + // Clearance + $regex = '/^(https?:\/\/)?bad-dragon\.com\/shop\/clearance/'; + if(preg_match($regex, $url, $matches) > 0) { + parse_str(parse_url($url, PHP_URL_QUERY), $urlParams); + + $this->setParam($urlParams, $params, 'type', 'ready_made'); + $this->setParam($urlParams, $params, 'type', 'flop'); + + if(isset($urlParams['skus'])) { + $skus = array(); + foreach($urlParams['skus'] as $sku) { + is_string($sku) && $skus[] = $sku; + is_array($sku) && $skus[] = $sku[0]; + } + $params['skus'] = implode(',', $skus); + } + + $this->setParam($urlParams, $params, 'sizes', 'onesize'); + $this->setParam($urlParams, $params, 'sizes', 'mini'); + $this->setParam($urlParams, $params, 'sizes', 'small'); + $this->setParam($urlParams, $params, 'sizes', 'medium'); + $this->setParam($urlParams, $params, 'sizes', 'large'); + $this->setParam($urlParams, $params, 'sizes', 'extralarge'); + + if(isset($urlParams['category'])) { + $params['category'] = strtolower($urlParams['category']); + } else{ + $params['category'] = 'all'; + } + + $this->setParam($urlParams, $params, 'firmnessValues', 'soft'); + $this->setParam($urlParams, $params, 'firmnessValues', 'medium', 'med_firm'); + $this->setParam($urlParams, $params, 'firmnessValues', 'firm'); + $this->setParam($urlParams, $params, 'firmnessValues', 'split'); + + if(isset($urlParams['price'])) { + isset($urlParams['price']['max']) + && $params['maxprice'] = $urlParams['price']['max']; + isset($urlParams['price']['min']) + && $params['minprice'] = $urlParams['price']['min']; + } + + isset($urlParams['cumtube']) + && $urlParams['cumtube'] === '1' + && $params['cumtube'] = 'on'; + isset($urlParams['suctionCup']) + && $urlParams['suctionCup'] === '1' + && $params['suctionCup'] = 'on'; + isset($urlParams['noAccessories']) + && $urlParams['noAccessories'] === '1' + && $params['noAccessories'] = 'on'; + + return $params; + } + + return null; + } + + public function getName() { + switch($this->queriedContext) { + case 'Sales': + return 'Bad Dragon Sales'; + case 'Clearance': + return 'Bad Dragon Clearance Search'; + default: + return parent::getName(); + } + } + + public function getURI() { + switch($this->queriedContext) { + case 'Sales': + return self::URI . 'sales'; + case 'Clearance': + return $this->inputToURL(); + default: + return parent::getURI(); + } + } + + public function collectData() { + switch($this->queriedContext) { + case 'Sales': + $sales = json_decode(getContents(self::URI . 'api/sales')) + or returnServerError('Failed to query BD API'); + + foreach($sales as $sale) { + $item = array(); + + $item['title'] = $sale->title; + $item['timestamp'] = strtotime($sale->startDate); + + $item['uri'] = $this->getURI() . '/' . $sale->slug; + + $contentHTML = '

'; + if(isset($sale->endDate)) { + $contentHTML .= '

This promotion ends on ' + . gmdate('M j, Y \a\t g:i A T', strtotime($sale->endDate)) + . '

'; + } else { + $contentHTML .= '

This promotion never ends

'; + } + $ul = false; + $content = json_decode($sale->content); + foreach($content->blocks as $block) { + switch($block->type) { + case 'header-one': + $contentHTML .= '

' . $block->text . '

'; + break; + case 'header-two': + $contentHTML .= '

' . $block->text . '

'; + break; + case 'header-three': + $contentHTML .= '

' . $block->text . '

'; + break; + case 'unordered-list-item': + if(!$ul) { + $contentHTML .= ''; + $ul = false; + } + $contentHTML .= '

' . $block->text . '

'; + break; + } + } + $item['content'] = $contentHTML; + + $this->items[] = $item; + } + break; + case 'Clearance': + $toyData = json_decode(getContents($this->inputToURL(true))) + or returnServerError('Failed to query BD API'); + + $productList = json_decode(getContents(self::URI + . 'api/inventory-toy/product-list')) + or returnServerError('Failed to query BD API'); + + foreach($toyData->toys as $toy) { + $item = array(); + + $item['uri'] = $this->getURI() + . '#' + . $toy->id; + $item['timestamp'] = strtotime($toy->created); + + foreach($productList as $product) { + if($product->sku == $toy->sku) { + $item['title'] = $product->name; + break; + } + } + + // images + $content = '

'; + foreach($toy->images as $image) { + $content .= ''; + } + // price + $content .= '

Price: $' + . $toy->price + // size + . '
Size: ' + . $toy->size + // color + . '
Color: ' + . $toy->color + // features + . '
Features: ' + . ($toy->suction_cup ? 'Suction cup' : '') + . ($toy->suction_cup && $toy->cumtube ? ', ' : '') + . ($toy->cumtube ? 'Cumtube' : '') + . ($toy->suction_cup || $toy->cumtube ? '' : 'None'); + // firmness + $firmnessTexts = array( + '2' => 'Extra soft', + '3' => 'Soft', + '5' => 'Medium', + '8' => 'Firm' + ); + $firmnesses = explode('/', $toy->firmness); + if(count($firmnesses) === 2) { + $content .= '
Firmness: ' + . $firmnessTexts[$firmnesses[0]] + . ', ' + . $firmnessTexts[$firmnesses[1]]; + } else{ + $content .= '
Firmness: ' + . $firmnessTexts[$firmnesses[0]]; + } + // flop + if($toy->type === 'flop') { + $content .= '
Flop reason: ' + . $toy->flop_reason; + } + $content .= '

'; + $item['content'] = $content; + + $enclosures = array(); + foreach($toy->images as $image) { + $enclosures[] = $image->fullFilename; + } + $item['enclosures'] = $enclosures; + + $categories = array(); + $categories[] = $toy->sku; + $categories[] = $toy->type; + $categories[] = $toy->size; + if($toy->cumtube) { + $categories[] = 'cumtube'; + } + if($toy->suction_cup) { + $categories[] = 'suction_cup'; + } + $item['categories'] = $categories; + + $this->items[] = $item; + } + break; + } + } + + private function inputToURL($api = false) { + $url = self::URI; + $url .= ($api ? 'api/inventory-toys?' : 'shop/clearance?'); + + // Default parameters + $url .= 'limit=60'; + $url .= '&page=1'; + $url .= '&sort[field]=created'; + $url .= '&sort[direction]=desc'; + + // Product types + $url .= ($this->getInput('ready_made') ? '&type[]=ready_made' : ''); + $url .= ($this->getInput('flop') ? '&type[]=flop' : ''); + + // Product names + foreach(array_filter(explode(',', $this->getInput('skus'))) as $sku) { + $url .= '&skus[]=' . urlencode(trim($sku)); + } + + // Size + $url .= ($this->getInput('onesize') ? '&sizes[]=onesize' : ''); + $url .= ($this->getInput('mini') ? '&sizes[]=mini' : ''); + $url .= ($this->getInput('small') ? '&sizes[]=small' : ''); + $url .= ($this->getInput('medium') ? '&sizes[]=medium' : ''); + $url .= ($this->getInput('large') ? '&sizes[]=large' : ''); + $url .= ($this->getInput('extralarge') ? '&sizes[]=extralarge' : ''); + + // Category + $url .= ($this->getInput('category') ? '&category=' + . urlencode($this->getInput('category')) : ''); + + // Firmness + if($api) { + $url .= ($this->getInput('soft') ? '&firmnessValues[]=3' : ''); + $url .= ($this->getInput('med_firm') ? '&firmnessValues[]=5' : ''); + $url .= ($this->getInput('firm') ? '&firmnessValues[]=8' : ''); + if($this->getInput('split')) { + $url .= '&firmnessValues[]=3/5'; + $url .= '&firmnessValues[]=3/8'; + $url .= '&firmnessValues[]=8/3'; + $url .= '&firmnessValues[]=5/8'; + $url .= '&firmnessValues[]=8/5'; + } + } else{ + $url .= ($this->getInput('soft') ? '&firmnessValues[]=soft' : ''); + $url .= ($this->getInput('med_firm') ? '&firmnessValues[]=medium' : ''); + $url .= ($this->getInput('firm') ? '&firmnessValues[]=firm' : ''); + $url .= ($this->getInput('split') ? '&firmnessValues[]=split' : ''); + } + + // Price + $url .= ($this->getInput('maxprice') ? '&price[max]=' + . $this->getInput('maxprice') : '&price[max]=300'); + $url .= ($this->getInput('minprice') ? '&price[min]=' + . $this->getInput('minprice') : '&price[min]=0'); + + // Features + $url .= ($this->getInput('cumtube') ? '&cumtube=1' : ''); + $url .= ($this->getInput('suctionCup') ? '&suctionCup=1' : ''); + $url .= ($this->getInput('noAccessories') ? '&noAccessories=1' : ''); + + return $url; + } +}