<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/rss-style.xsl" type="text/xsl"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	     xmlns:dc="http://purl.org/dc/elements/1.1/"
	   xmlns:atom="http://www.w3.org/2005/Atom"
	     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>Amazon &#8211; Terence Eden’s Blog</title>
	<atom:link href="https://shkspr.mobi/blog/tag/amazon/feed/" rel="self" type="application/rss+xml" />
	<link>https://shkspr.mobi/blog</link>
	<description>Regular nonsense about tech and its effects 🙃</description>
	<lastBuildDate>Thu, 26 Feb 2026 09:09:30 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shkspr.mobi/blog/wp-content/uploads/2023/07/cropped-avatar-32x32.jpeg</url>
	<title>Amazon &#8211; Terence Eden’s Blog</title>
	<link>https://shkspr.mobi/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title><![CDATA[Improving PixelMelt's Kindle Web Deobfuscator]]></title>
		<link>https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/</link>
					<comments>https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 19 Oct 2025 11:34:37 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[drm]]></category>
		<category><![CDATA[ebooks]]></category>
		<category><![CDATA[kindle]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=64017</guid>

					<description><![CDATA[A few days ago, someone called PixelMelt published a way for Amazon&#039;s customers to download their purchased books without DRM. Well… sort of.  In their post &#34;How I Reversed Amazon&#039;s Kindle Web Obfuscation Because Their App Sucked&#34; they describe the process of spoofing a web browser, downloading a bunch of JSON files, reconstructing the obfuscated SVGs used to draw individual letters, and running O…]]></description>
										<content:encoded><![CDATA[<p>A few days ago, someone called PixelMelt published a way for Amazon's customers to download their purchased books without DRM. Well… <em>sort of</em>.</p>

<p>In their post "<a href="https://blog.pixelmelt.dev/kindle-web-drm/">How I Reversed Amazon's Kindle Web Obfuscation Because Their App Sucked</a>" they describe the process of spoofing a web browser, downloading a bunch of JSON files, reconstructing the obfuscated SVGs used to draw individual letters, and running OCR on them to extract text.</p>

<p>There were a few problems with this approach.</p>

<p>Firstly, the downloader was hard-coded to only work with the .com site. That fix was simple - do a search and replace on <code>amazon.com</code> with <code>amazon.co.uk</code>. Easy!</p>

<p>But the harder problem was with the OCR. The code was designed to visually centre each extracted glyph. That gives a nice amount of whitespace around the character which makes it easier for OCR to run. The only problem is that some characters are ambiguous when centred:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/10/centred-fs8.png" alt="Several letters drawn with vertical centering." width="1134" height="177" class="aligncenter size-full wp-image-64025">

<p>When I ran the code, lots of full-stops became midpoints, commas became apostrophes, and various other characters went a bit wonky.</p>

<p>That made the output rather hard to read. This was compounded by the way line-breaks were treated. Modern eBooks are designed to be reflowable - no matter the size of your screen, lines should only break on a new paragraph. This had forced linebreaks at the end of every displayed line - rather than at the end of a paragraph.</p>

<p>So I decided to fix it.</p>

<h2 id="a-new-approach"><a href="https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/#a-new-approach">A New Approach</a></h2>

<p>I decided that OCRing an entire page would yield better results than single characters. I was (mostly) right.  Here's what a typical page looks like after de-obfuscation and reconstruction:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/10/sample-page.webp" alt="A page of text." width="500" height="800" class="aligncenter size-full wp-image-64027">

<p>As you can see - the typesetting is good for the body text, but skew-whiff for the title. Bold and italics are preserved. There are no links or images.</p>

<p>Here's how I did it.</p>

<h3 id="extract-the-characters"><a href="https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/#extract-the-characters">Extract the characters</a></h3>

<p>As in the original code, I took the SVG path of the character and rendered it as a monochrome PNG. Rather than centring the glyph, I used the height and width provided in the <code>glyphs.json</code> file. That gave me a directory full of individual letters, numbers, punctuation marks, and ligatures. These were named by fontKey (bold, italic, normal, etc).</p>

<h3 id="create-a-blank-page"><a href="https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/#create-a-blank-page">Create a blank page</a></h3>

<p>The <code>page_data_0_4.json</code> has a width and height of the page. I created a white PNG with the same dimensions. The individual characters could then be placed on that.</p>

<h3 id="resize-the-characters"><a href="https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/#resize-the-characters">Resize the characters</a></h3>

<p>In the <code>page_data_0_4.json</code> each run of text has a fontKey - which allows the correct glyph to be selected. There's also a <code>fontSize</code> parameter. Most text seems to be (the ludicrously precise) <code>19.800001</code>. If a font had a different size, I temporarily scaled the glyph in proportion to 19.8.</p>

<p>Each glyph has an associated <code>xPosition</code>, along with a <code>transform</code> which gives X and Y offsets.  That allows for indenting and other text layouts.</p>

<p>The characters were then pasted on to the blank page.</p>

<p>Once every character from that page had been extracted, resized, and placed - the page was saved as a monochrome PNG.</p>

<h3 id="ocr-the-page"><a href="https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/#ocr-the-page">OCR the page</a></h3>

<p><a href="https://tesseract-ocr.github.io/tessdoc/">Tesseract 5</a> is a fast, modern, and <em>reasonably</em> accurate OCR engine for Linux.</p>

<p>Running <code>tesseract page_0022.png output -l eng</code> produced a .txt file with all the text extracted.</p>

<p>For a more useful HTML style layout, the <a href="https://en.wikipedia.org/wiki/HOCR">hOCR output</a> can be used: <code>tesseract page_0022.png output -l eng hocr</code></p>

<p>Or, a PDF with embedded text: <code>tesseract page_0022.png output -l eng pdf</code></p>

<h3 id="mistakes"><a href="https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/#mistakes">Mistakes</a></h3>

<p>OCR isn't infallible. Even with a high resolution image and a clear font, there were some errors.</p>

<ul>
<li>Superscript numerals for footnotes were often missing from the OCR.</li>
<li>Words can run together even if they are well spaced.</li>
<li>Tesseract can recognise bold and italic characters - but it outputs everything as plain text.</li>
</ul>

<h2 id="whats-missing"><a href="https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/#whats-missing">What's missing?</a></h2>

<p>Images aren't downloaded. I took a brief look and, while there are links to them in the metadata, they're downloaded as encrypted blobs. I'm not clever enough to do anything with them.</p>

<p>The OCR can't pick out semantic meaning. Chapter headings and footnotes are rendered the same way as text.</p>

<p>Layout is flat. The image of the page might have an indent, but the outputted text won't.</p>

<h2 id="whats-next"><a href="https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/#whats-next">What's next?</a></h2>

<p>This is very far from perfect. It can give you a visually <em>similar</em> layout to a book you have purchased from Amazon. But it won't be reflowable.</p>

<p>The text will be <em>reasonably</em> accurate. But there will be plenty of mistakes.</p>

<p>You can get an HTML layout with hOCR. But it will be missing formatting and links.</p>

<p>Processing all the JSON files and OCRing all the images is <em>relatively</em> quick. But tweaking and assembling is still fairly manual.</p>

<p>There's nothing particularly clever about what I've done. The original code didn't come with an open source software licence, so I am unable to share my changes - but any moderately competent programmer could recreate this.</p>

<p>Personally, I've just stopped buying books from Amazon. I find that <a href="https://shkspr.mobi/blog/2025/02/automatic-kobo-and-kindle-ebook-arbitrage/">Kobo is often cheaper</a> and their DRM is easy to bypass. But if you have many books trapped in Amazon - or a book is only published there - this is a barely adequate way to liberate it for your personal use.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=64017&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/10/improving-pixelmelts-kindle-web-deobfuscator/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Book Review: The World After Amazon - Stories from Amazon Workers by Xenia Benivolski ★★★☆☆]]></title>
		<link>https://shkspr.mobi/blog/2025/07/book-review-the-world-after-amazon-stories-from-amazon-workers-by-xenia-benivolski/</link>
					<comments>https://shkspr.mobi/blog/2025/07/book-review-the-world-after-amazon-stories-from-amazon-workers-by-xenia-benivolski/#respond</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 09 Jul 2025 11:34:09 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[Book Review]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=61798</guid>

					<description><![CDATA[This is a brilliant idea for a short story collection. Gather a group of non-writers, all of whom have experienced the dystopia of working for Amazon, and support them to write speculative science fiction.  Given how futuristic Amazon is, perhaps they have a unique insight into what its future holds.  Or, as the rather academic intro puts it:  The Worker as Futurist project asks another question: …]]></description>
										<content:encoded><![CDATA[<p>This is a brilliant idea for a short story collection. Gather a group of non-writers, all of whom have experienced the dystopia of working for Amazon, and support them to write speculative science fiction.  Given how futuristic Amazon is, perhaps they have a unique insight into what its future holds.  Or, as the rather academic intro puts it:</p>

<blockquote><p>The Worker as Futurist project asks another question: if SF is so important to the operations of capitalism in the twenty-first century, does it also have a radical potential that might lend itself to the struggles of workers and other oppressed people within, against and beyond that system? (see Jameson 2005; Roke 2020)</p></blockquote>

<p>I'll be honest, it feels a <em>little</em> patronising.  The project articulates its theory of change (which only <em>slightly</em> puts me in mind of <a href="https://charles-harris.co.uk/2019/11/does-satire-work/">Peter Cook's famous quote</a>) - hoping that radical fiction might move mountains:</p>

<blockquote><p>We at the Worker as Futurist project believe that workers can fruitfully understand, theorize, and plot forms of resistance to capitalism through creative expression, especially through the process of writing, particularly within the genre of SF. If, as we have argued, SF is now active in important ways at the very heart of capitalism, maybe that genre is also somehow the system’s achilles’ heel?</p></blockquote>

<p>Still, it makes for a fascinating introduction to a somewhat uneven set of stories.  There is some delightfully weird fiction - I especially enjoyed the idea of the University of the Phoenix using AI to write curses on corporations. In amongst that there's some fairly standard stories of worker exploitation, a few overwritten pieces, and one or two which would make great full length books.</p>

<p>The afterword is very clear about the reason for this book existing:</p>

<blockquote><p>To me, it never mattered whether or not the stories written by the workers in this project would be considered “good” by the well-read literary elite. To me, it only mattered that those who took up the challenge wrote. And by writing, and by speaking their truths, they exploded the paradigm that would render their subjectivity nonexistent.</p></blockquote>

<p>And I heartily agree with that. I'd rather read a new writer explore the problem-space rather than yet-another trilogy about romance magicians.</p>

<p>The book is free to download or, if you think the master's tools can dismantle the master's house, you can purchase a copy on Amazon.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=61798&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/07/book-review-the-world-after-amazon-stories-from-amazon-workers-by-xenia-benivolski/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Automatic Kobo and Kindle eBook Arbitrage]]></title>
		<link>https://shkspr.mobi/blog/2025/02/automatic-kobo-and-kindle-ebook-arbitrage/</link>
					<comments>https://shkspr.mobi/blog/2025/02/automatic-kobo-and-kindle-ebook-arbitrage/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 19 Feb 2025 12:34:43 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[ebooks]]></category>
		<category><![CDATA[kindle]]></category>
		<category><![CDATA[kobo]]></category>
		<category><![CDATA[python]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=58241</guid>

					<description><![CDATA[This post will show you how to programmatically get the cheapest possible price on eBooks from Kobo.  Background  Amazon have decided to stop letting customers download their purchased eBooks onto their computers. That means I can&#039;t strip the DRM and read on my non-Amazon eReader.  So I guess I&#039;m not spending money with Amazon any more. I&#039;m moving to Kobo for three main reasons:   They provide…]]></description>
										<content:encoded><![CDATA[<p>This post will show you how to programmatically get the cheapest possible price on eBooks from Kobo.</p>

<h2 id="background"><a href="https://shkspr.mobi/blog/2025/02/automatic-kobo-and-kindle-ebook-arbitrage/#background">Background</a></h2>

<p>Amazon have decided to stop letting customers download their purchased eBooks onto their computers. That means I can't strip the DRM and read on my non-Amazon eReader.</p>

<p>So I guess I'm not spending money with Amazon any more. I'm moving to Kobo for three main reasons:</p>

<ol>
<li>They provide standard ePubs for download.</li>
<li>ePub DRM is trivial to remove.</li>
<li>Kobo will <em>undercut</em> Amazon's prices!</li>
</ol>

<p>Here's the thing. I <em>want</em> to <strong>buy</strong> my eBooks. It is <a href="https://goodereader.com/blog/e-book-news/where-do-consumers-get-their-e-books-from">trivial to pirate almost any modern book</a>. But, call me crazy, I like rewarding writers with a few pennies. That said, I'm not made of money, so I want to get the best (legal) deal possible.</p>

<p><a href="https://www.kobo.com/gb/en/p/pricematch-about">Kobo do a price-match with other eBook retailers</a>. It says:</p>

<blockquote><p>We'll award a credit to your Kobo account equal to the price difference, <strong>plus 10% of the competitor’s price</strong>.</p></blockquote>

<p>I found a book I wanted which was £4.99 on Kobo. The Amazon Kindle price was £4.31.</p>

<p><code>4.99 - ( (4.99 - 4.31) + (4.31 * 0.1) ) = 3.88</code></p>

<p>I purchased the book, sent a request for a price match, and got this email a few hours later:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/02/kobo.png" alt="﻿We’re pleased to confirm that the price match you requested has been successfully processed. The credit has been applied to your Kobo account. ﻿Credit amount: £ 1.11 GBP" width="1008" height="756" class="aligncenter size-full wp-image-58242">

<p>OK! So what steps can we automate, and which will have to remain manual?</p>

<h2 id="amazon-pricing-api"><a href="https://shkspr.mobi/blog/2025/02/automatic-kobo-and-kindle-ebook-arbitrage/#amazon-pricing-api">Amazon Pricing API</a></h2>

<p>Amazon have a <a href="https://webservices.amazon.com/paapi5/documentation/">Product Advertising API</a>. You will need to register for the <a href="https://affiliate-program.amazon.co.uk/">Amazon Affiliate Program</a> and make some qualifying sales before you get API access.</p>

<p>In order to search for an ISBN and get the price back, you need to send:</p>

<pre><code class="language-json">{
 "Keywords": "isbn:9781473613546",
 "Resources": ["Offers.Listings.Price"],
}
</code></pre>

<p>Using <a href="https://github.com/LeilaSchooley/paapi5-python-sdk">the updated Python API for PAAPI</a>:</p>

<pre><code class="language-python">from paapi5_python_sdk import DefaultApi, SearchItemsRequest, SearchItemsResource, PartnerType

def search_items():
    access_key = "ABC"
    secret_key = "123"
    partner_tag = "shkspr-21"
    host = "webservices.amazon.co.uk"
    region = "eu-west-1"

    api = DefaultApi(access_key=access_key, secret_key=secret_key, host=host, region=region)

    request = SearchItemsRequest(
        partner_tag=partner_tag,
        partner_type=PartnerType.ASSOCIATES,
        keywords="isbn:9781473613546",
        search_index="All",
        item_count=1,
        resources=["Offers.Listings.Price"]
    )

    response = api.search_items(request)

    print(response)

search_items()
</code></pre>

<p>(Add your own access key, secret key, and tag. You may need to change the host and region depending on where you are in the world.)</p>

<p>That returns something like:</p>

<pre><code class="language-json">{
    "search_result": {
        "items": [
            {
                "asin": "B09JLQHHXN",
                "detail_page_url": "https://www.amazon.co.uk/dp/B09JLQHHXN?tag=shkspr-21&amp;linkCode=osi&amp;th=1&amp;psc=1",
                "offers": {
                    "listings": [
                        {
                            "price": {
                                "amount": 2.99,
                                "currency": "GBP",
                                "display_amount": "£2.99"
                            }
                        }
                    ]
                }
            }
        ]
    }
}
</code></pre>

<p>(I've truncated the above so it only shows the relevant information.)</p>

<h2 id="kobo-isbn-price"><a href="https://shkspr.mobi/blog/2025/02/automatic-kobo-and-kindle-ebook-arbitrage/#kobo-isbn-price">Kobo ISBN &amp; Price</a></h2>

<p>Let's get the ISBN and Price of a book on Kobo. There's no easy API to do this. But, thankfully, Kobo embeds some Schema.org metadata.</p>

<p>Look at the source code for <a href="https://www.kobo.com/gb/en/ebook/venomous-lumpsucker-1">https://www.kobo.com/gb/en/ebook/venomous-lumpsucker-1</a></p>

<pre><code class="language-html">&lt;div id="ratings-widget-details-wrapper" class="kobo-gizmo"
     data-kobo-gizmo="RatingAndReviewWidget"
     data-kobo-gizmo-config ='{&amp;quot;googleBook&amp;quot;:&amp;quot;{\r\n  \&amp;quot;@context\&amp;quot;: \&amp;quot;http://schema.org\&amp;quot;,\r\n  \&amp;quot;@type\&amp;quot;: \&amp;quot;Book\&amp;quot;,\r\n  \&amp;quot;name\&amp;quot;: \&amp;quot;Venomous Lumpsucker\&amp;quot;,\r\n  \&amp;quot;genre\&amp;quot;: [\r\n    \&amp;quot;Fiction \\u0026 Literature\&amp;quot;,\r\n    \&amp;quot;Humorous\&amp;quot;,\r\n    \&amp;quot;Literary\&amp;quot;\r\n  ],\r\n  \&amp;quot;inLanguage\&amp;quot;: \&amp;quot;en\&amp;quot;,\r\n  \&amp;quot;author\&amp;quot;: {\r\n    \&amp;quot;@type\&amp;quot;: \&amp;quot;Person\&amp;quot;,\r\n    \&amp;quot;name\&amp;quot;: \&amp;quot;Ned Beauman\&amp;quot;\r\n  },\r\n  \&amp;quot;workExample\&amp;quot;: {\r\n    \&amp;quot;@type\&amp;quot;: \&amp;quot;Book\&amp;quot;,\r\n    \&amp;quot;author\&amp;quot;: {\r\n      \&amp;quot;@type\&amp;quot;: \&amp;quot;Person\&amp;quot;,\r\n      \&amp;quot;name\&amp;quot;: \&amp;quot;Ned Beauman\&amp;quot;\r\n    },\r\n    \&amp;quot;isbn\&amp;quot;: \&amp;quot;9781473613546\&amp;quot; …'&gt;
&lt;/div&gt;
</code></pre>

<p>Getting the data from the <code>data-kobo-gizmo-config</code> is a little tricky.</p>

<ul>
<li>Using Python Requests won't work because Kobo seem to run a JS CAPTCHA to detect scraping.</li>
<li>There is a <a href="https://github.com/janeczku/calibre-web/wiki/Kobo-Integration">Calibre-Web Kobo plugin</a> but it requires you to have a physical Kobo eReader in order to get an API key.</li>
<li>The <a href="https://webservice.rakuten.co.jp/explorer/api">Rakuten API</a> is only for the Japanese store.</li>
</ul>

<p>So we have to use the <a href="https://www.selenium.dev/documentation/webdriver/">Selenium WebDriver</a> to scrape the data:</p>

<pre><code class="language-python">from selenium import webdriver
from bs4 import BeautifulSoup
import json

#   Open the web page
browser = webdriver.Firefox()
browser.get("https://www.kobo.com/gb/en/ebook/venomous-lumpsucker-1")

#   Get the source
html_source = browser.page_source

#   Soupify
soup = BeautifulSoup(html_source, 'html.parser')

#   Get the encoded JSON Schema
schema = soup.find_all(id="ratings-widget-details-wrapper")[0].get("data-kobo-gizmo-config")

#   Convert to object from JSON
parsed_data = json.loads(schema)

#   Decode the nested JSON strings
parsed_data["googleBook"] = json.loads(parsed_data["googleBook"])

#    Get ISBN and Price
price = parsed_data["googleBook"]["workExample"]["potentialAction"]["expectsAcceptanceOf"]["price"]
isbn  = parsed_data["googleBook"]["workExample"]["isbn"]
print(isbn)
print(price)
</code></pre>

<h2 id="kobo-wishlist"><a href="https://shkspr.mobi/blog/2025/02/automatic-kobo-and-kindle-ebook-arbitrage/#kobo-wishlist">Kobo Wishlist</a></h2>

<p>OK, nearly there! Given a Kobo book URl we can get the price and ISBN, then use that ISBN to get the Kindle price.  But how do we get the Kobo book URl in the first place?</p>

<p>I'm adding all the books I want to my <a href="https://www.kobo.com/blog/how-to-use-the-kobo-wishlist-feature">Kobo Wishlist</a>.</p>

<p>Inside the Wishlist is a scrap of JavaScript which contains this JSON:</p>

<pre><code class="language-json">{
    "value": {
        "Items": [
            {
                "Title": "Venomous Lumpsucker",
                "Price": "£2.99",
                "ProductUrl": "/gb/en/ebook/venomous-lumpsucker-1",
            }
        ],
        "TotalItemCount": 11,
        "ItemCountByProductType": {
            "book": 11
        },
        "PageIndex": 1,
        "TotalNumPages": 1,
       }
}
</code></pre>

<p>(Simplified to make it easier to understand.)</p>

<p>Although there's a price, there's no ISBN, So you'll need to use the "ProductUrl" to get the ISBN and Price as above.</p>

<p>Sadly, unlike Amazon, there's no way to publicly share a wishlist. Getting the JSON requires logging in, so it's back to Selenium again!</p>

<p>This should be enough:</p>

<pre><code class="language-python">from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup
import time

browser = webdriver.Firefox()
browser.get("https://www.kobo.com/gb/en/account/wishlist")

#       Log in
username_box = browser.find_element(By.NAME, "LogInModel.UserName")
username_box.clear()
username_box.send_keys('you@example.com')

password_box = browser.find_element(By.NAME, "LogInModel.Password")
password_box.clear()
password_box.send_keys('p455w0rd')

password_box.send_keys(Keys.RETURN)

time.sleep(5) # Wait for load and rendering
</code></pre>

<p>But the Kobo presents a CAPTCHA which prevents login.</p>

<p>There is an <em>unofficial</em> API which, sadly, <a href="https://github.com/subdavis/kobo-book-downloader/issues/121">doesn't seem to work at the moment</a>.</p>

<h2 id="next-steps"><a href="https://shkspr.mobi/blog/2025/02/automatic-kobo-and-kindle-ebook-arbitrage/#next-steps">Next Steps</a></h2>

<p>For now, I'm saving specific Kobo book URls into a file and then running a scrape once per day. Hopefully, the <a href="https://github.com/subdavis/kobo-book-downloader/">unofficial Kobo API</a> will be working again soon.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=58241&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/02/automatic-kobo-and-kindle-ebook-arbitrage/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Sarcasm Detection and Cultural Hegemony]]></title>
		<link>https://shkspr.mobi/blog/2023/07/sarcasm-detection-and-cultural-hegemony/</link>
					<comments>https://shkspr.mobi/blog/2023/07/sarcasm-detection-and-cultural-hegemony/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 04 Jul 2023 11:34:52 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[customer service]]></category>
		<category><![CDATA[language]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=46169</guid>

					<description><![CDATA[Way back in the 1990s, my family visited the USA. It seemed at every single large shop there was a person stood inside whose sole job was to say &#34;Welcome to STORENAME! How are you doing today? We&#039;re so pleased to have you shop with us!&#34; - their face plastered with an enormous grin.  It was quite the culture shock.  To us, it felt weird, insincere, and creepy. But, like the over-enthusiastic…]]></description>
										<content:encoded><![CDATA[<p>Way back in the 1990s, my family visited the USA. It seemed at every single large shop there was a person stood inside whose sole job was to say "Welcome to STORENAME! How are you doing today? We're so pleased to have you shop with us!" - their face plastered with an enormous grin.</p>

<p>It was <em>quite</em> the culture shock.</p>

<p>To us, it felt weird, insincere, and creepy. But, like the over-enthusiastic whooping and cheering from US sitcom audiences, it seemed to be an accepted part of the culture.</p>

<p>A few years later, the Disney Store in the UK decided that they needed to import this style of greater.  I remember walking into a store and seeing a clearly mortified teenager reciting the same spiel as in the American stores.</p>

<p>It was <em>not</em> a success. British culture doesn't really do over-the-top, flowery, purple-prose. It reads to us as sarcasm.  I'm not saying this is an attractive characteristic of the average Britisher - but it is noticeable. It causes great cognitive dissonance when American friends and colleagues give us praise - <em>surely</em> they are being insincere? But, no, everything <em>is</em> awesome to them.</p>

<p>With the rise of International English, most countries' linguistic foibles get absorbed into the zeitgeist. We do the needful once we have circled back and then get into a muddle over what the verb "to table" means. Mostly, it works. Mostly.</p>

<p>Recently, I had a chat with an Amazon UK customer service assistant. I assume that they weren't in the UK and were outsourced to a country where the weather is hotter and the standard of written English is good enough.  They were incredibly helpful so I finished my conversation with a well-intentioned "have a lovely day".</p>

<p>In return, I got this:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/06/amazon-fs8.png" alt="&quot;Wish you a day filled with light, happiness and smiles. It has been my pleasure helping a valued customer like you today Thank you for doing Business with Amazon! Hope you and your family are safe Have a great day ahead. Your success is also our success!&quot;" width="695" height="504" class="aligncenter size-full wp-image-46170">

<p>Wow! My initial thought was that they were being <em>heavily</em> sarcastic. If someone in a UK shop had said that to me in person, I'd assume they wanted to step outside for a punch-up. Seriously, that's fighting words over here! And the implied threat to my family...?</p>

<p>Of course, it is none of that. They probably have a list of canned responses which they can pre-select. Responses which have been extensively focus-grouped and found to be <em>awesome</em>.  Or maybe I wasn't talking to a human - perhaps a bot just decided to repay my compliment as though I were an American.</p>

<p>Anyway, if you're doing prompt-engineering on an LLM please be sure to set the sarcasm detection to the lowest common denominator!</p>

<hr>

<h3 id="reactions-from-the-fediverse"><a href="https://shkspr.mobi/blog/2023/07/sarcasm-detection-and-cultural-hegemony/#reactions-from-the-fediverse">Reactions from the Fediverse</a></h3>

<iframe src="https://indieweb.social/@whalecoiner/110621658035226624/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="500" height="250" allowfullscreen="allowfullscreen"></iframe>

<iframe src="https://mastodon.world/@Mayor_of_Smartarse/110621615426550939/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="500" height="250" allowfullscreen="allowfullscreen"></iframe>

<iframe src="https://spore.social/@immersfer/110621588503721759/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="500" height="250" allowfullscreen="allowfullscreen"></iframe>

<iframe src="https://toot.ale.gd/@yvan/110621578124814979/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="500" height="400" allowfullscreen="allowfullscreen"></iframe>

<iframe src="https://kolektiva.social/@isaaccp/110621563139139055/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="500" height="250" allowfullscreen="allowfullscreen"></iframe>

<iframe src="https://mstdn.social/@darkling/110621494102466647/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="500" height="250" allowfullscreen="allowfullscreen"></iframe>

<iframe src="https://front-end.social/@sarajw/110621467281341371/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="500" height="500" allowfullscreen="allowfullscreen"></iframe>

<iframe src="https://bytetower.social/@crinolinerobot/110621463990723941/embed" class="mastodon-embed" style="max-width: 100%; border: 0" width="500" height="250" allowfullscreen="allowfullscreen"></iframe>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=46169&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/07/sarcasm-detection-and-cultural-hegemony/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Why does Alexa speak to me in German?]]></title>
		<link>https://shkspr.mobi/blog/2022/06/why-does-alexa-speak-to-me-in-german/</link>
					<comments>https://shkspr.mobi/blog/2022/06/why-does-alexa-speak-to-me-in-german/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 18 Jun 2022 11:34:35 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[alexa]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[Mary Robinette Kowal]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=42752</guid>

					<description><![CDATA[I speak English. My Amazon account is set to English. My Alexa listens to my English commands and replies in English.  Except for new book notifications.  I saw a pulsing yellow light on the dot. I&#039;ve memorised all of the various signs and portents the accurs&#039;d device can summon up, so I asked it (in English) what notifications it had for me.  It replied, naturally, in German.  I couldn&#039;t grab an …]]></description>
										<content:encoded><![CDATA[<p>I speak English. My Amazon account is set to English. My Alexa listens to my English commands and replies in English.</p>

<p>Except for new book notifications.</p>

<p>I saw a pulsing yellow light on the dot. I've memorised all of the various signs and portents the accurs'd device can summon up, so I asked it (in English) what notifications it had for me.  It replied, naturally, in German.</p>

<p>I couldn't grab an audio recording in time, and I've no idea which command invokes a repetition. But the Alexa app contains a handy history of every utterance to spew forth from its speaker.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2022/05/german1.jpeg" alt="Screenshot which says &quot;1 new notification from Amazon shopping: ‘Ein Autor, dem Sie auf Amazon folgen, Mary Robinette Kowal, hat ein neues Buch mit dem Namen Die Berechnung der Sterne: Roman veröffentlicht.’&quot;" width="680" height="510" class="aligncenter size-full wp-image-42753">

<p>To be clear, my IP address shows that I am in the UK. I have never bough German lager from Amazon. I've never watched <i lang="de">Das Boot</i> on Amazon Prime. I haven't even asked Alexa to play the soundtrack to Cabaret!</p>

<p>Whatever. Eine Kline Glitche um Der Matrix.</p>

<p>And then, a few weeks later, it happened again!</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2022/05/German-2.jpg" alt="Screenshot of an Alexa notification.  Amazon Follow: New Book Release.  Amazon Follow updates via Alexa.   Want to add Die Galaxie und das Licht darin by Becky Chambers to your Amazon wish list?" width="680" height="511" class="aligncenter size-full wp-image-42755">

<p><i lang="de">Was ist das? Ein großer Haufen Schweinescheiße!</i></p>

<p>To be even clearer - neither of the authors are German. I stopped learning German when I was 14. My <i lang="de">liebe Frau</i> happens to have German A-Level but she swears blind that she only uses it to speak with Hans, our <i lang="de">flaschenspüler</i> - and never in front of Alexa.</p>

<p>So what gives?</p>

<p>As far as I can tell, neither of these authors has a <strong>new</strong> book out. But a German translation of their work has been published. Amazon knows I follow these authors and, because Amazon are <i lang="de">Kapitalistische Warzenschweinficker</i>, will gently encourage me to by more of their works.  Ordinarily, that might be useful. But as I don't speak the language, it's all a bit pointless.</p>

<p>For some reason, this only seems to happen with German translations. No idea why.</p>

<p>It seems that Amazon's prowess in deep-artificial-learning-neural-technobabble doesn't actually extend to anything useful - like making sure it doesn't read out garbled multilingual sentences.</p>

<p>What a bunch of <i lang="de">Kartoffelköpfe!</i></p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=42752&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2022/06/why-does-alexa-speak-to-me-in-german/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Use Python to get alerted when an Amazon wishlist item drops in price]]></title>
		<link>https://shkspr.mobi/blog/2022/01/use-python-to-get-alerted-when-an-amazon-wishlist-item-drops-in-price/</link>
					<comments>https://shkspr.mobi/blog/2022/01/use-python-to-get-alerted-when-an-amazon-wishlist-item-drops-in-price/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 22 Jan 2022 12:34:54 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[wishlist]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=41673</guid>

					<description><![CDATA[Scratching my own itch. I want an alert when there&#039;s been a price drop on an item on my Amazon wishlist.  I couldn&#039;t find an easy way to get an email directly from Amazon (customer-focused my shiny metal arse) so I knocked something up in Python. This is heavily inspired by Leigh Dodds&#039; Wishlist Monitor.  Amazon don&#039;t offer an API for wishlists (innovative my shiny metal arse). So this uses…]]></description>
										<content:encoded><![CDATA[<p>Scratching my own itch. I want an alert when there's been a price drop on an item on my Amazon wishlist.  I couldn't find an easy way to get an email directly from Amazon (customer-focused my shiny metal arse) so I knocked something up in Python. This is heavily inspired by <a href="https://github.com/ldodds/wishlist-monitor">Leigh Dodds' Wishlist Monitor</a>.</p>

<p>Amazon don't offer an API for wishlists (innovative my shiny metal arse). So this uses Beautiful Soup to grab the data from the HTML. To be fair, there's also <em>some</em> microdata on the page, which makes things slightly easier.</p>

<p>The code is available on <a href="https://github.com/edent/Amazon-Wishlist-Pricedrop-Alert">github.com/edent/Amazon-Wishlist-Pricedrop-Alert</a> - but here's a brief walkthrough of parsing and dealing with pagination:</p>

<p>First up, the standard boilerplate for getting and parsing HTML</p>

<pre><code class="language-python">from bs4 import BeautifulSoup
import requests
import re
import json
</code></pre>

<p>I start by passing this function my wishlist URL <a href="https://www.amazon.co.uk/gp/registry/wishlist/1A1NYHTAZ3N6V/"></a><a href="https://www.amazon.co.uk/gp/registry/wishlist/1A1NYHTAZ3N6V/">https://www.amazon.co.uk/gp/registry/wishlist/1A1NYHTAZ3N6V/</a>. 
Amazon only returns 10 items per page of HTML, but it includes a "pagination" URL at the end of each page. Later on, we'll recursively call this function based on the "next page" URL.</p>

<pre><code class="language-python">def get_wishlist(url):
    #   Load the wishlist
    response = requests.get(url)
    page_html = response.text
    #   Parse the page
    soup = BeautifulSoup(page_html, 'html.parser')
    return soup
</code></pre>

<p>The item name - for example "Fly Fishing by JR Hartley" - needs to be scraped out of the HTML. It looks something like this:</p>

<pre><code class="language-html">&lt;a id="itemName_IS7IZUKCMTBZG" 
   class="a-link-normal" 
   title="Fly Fishing by JR Hartley"
   href="..."&gt;
   Fly Fishing by JR Hartley
&lt;/a&gt;
</code></pre>

<p>Use BeautifulSoup to grab the string inside the anchor. Use a regex to match anything starting with <code>itemName_</code>.</p>

<pre><code class="language-python">def get_items(soup):
    #   Get the item names
    for match in soup.find_all('a', id=re.compile("itemName_")):
        item = match.string.strip()
        item_list.append(item)
</code></pre>

<p>Prices and product IDs are slightly easier to scrape. They have microdata and JSON. For example:</p>

<pre><code class="language-html">&lt;li data-id="1A1NYHTAZ3N6V"
    data-itemId="I3VQB497DB6HJF"
    data-price="8.07"
    data-reposition-action-params="{"hasComparisonTable":false,"itemExternalId":"ASIN:B0962VD2G8|A1F83G8C2ARO7P","listType":"WishList","sid":"260-3142506-2992056"}"
    class="a-spacing-none g-item-sortable"&gt;...
</code></pre>

<p>The JSON in <code>data-reposition-action-params</code> parses out to:</p>

<pre><code class="language-json">{
  "hasComparisonTable": false,
  "itemExternalId": "ASIN:B0962VD2G8|A1F83G8C2ARO7P",
  "listType": "WishList",
  "sid": "260-3142506-2992056"
}
</code></pre>

<p>Beautiful soup can grab the <code>data-price</code> and then the Amazon ID:</p>

<pre><code class="language-python">def get_prices_and_ids(soup):
    #   Get the price and ID from data attributes
    for match in soup.find_all("li", class_="g-item-sortable"):
        price = match.attrs["data-price"]
        price_list.append(price)
        json_data = json.loads(match.attrs["data-reposition-action-params"])
        # Will be something like "ASIN:B095PV5G87|A1F83G8C2ARO7P"
        id = json_data["itemExternalId"].split(":")[1].split("|")[0]
        id_list.append(id)
</code></pre>

<p>That will get us all the names, IDs, and prices on the first page. What about subsequent pages?</p>

<p>At the bottom of the page is this HTML:</p>

<pre><code class="language-html">&lt;input
   type="hidden"
   name="showMoreUrl"
   value="/hz/wishlist/slv/items?filter=unpurchased&amp;paginationToken=eyJGcm9tVV...MDl9&amp;itemsLayout=LIST&amp;sort=default&amp;type=wishlist&amp;lid=1A1NYHTAZ3N6V"
   class="showMoreUrl"/&gt;
</code></pre>

<p>Retrieving the URL gives another HTML page with the next set of wishlist items on it.  The last page of results has <code>&lt;div id="endOfListMarker"&gt;</code> which we can use to detect when to stop getting pages.</p>

<pre><code class="language-python">def get_paginator(soup):
    paginator = None
    ##  Find the paginator
    if soup.find("div", {"id": "endOfListMarker"}) is None:
        #   If the end tag doesn't exist, continue
        for match in soup.find_all('input', class_="showMoreUrl"):
            paginator = "https://www.amazon.co.uk" + match.attrs["value"]
    else:
        paginator = None
    return paginator
</code></pre>

<p>Putting it all together looks like this:</p>

<pre><code class="language-python">#   Set up the lists
item_list  = []
price_list = []
id_list    = []

#   Message text
message = "Here are the recent price drops:\n"

def get_all(url):
    global counter
    counter = counter + 1
    print( "Getting page " + str(counter))
    soup = get_wishlist(url)
    get_items(soup)
    get_prices_and_ids(soup)
    paginator = get_paginator(soup)
    if paginator is not None:
        get_all(paginator)

#   Get all the items on the wishlist
#   Which page are we on?
counter = 0
get_all("https://www.amazon.co.uk/gp/registry/wishlist/1A1NYHTAZ3N6V/")
</code></pre>

<p>That stores all the data in some lists. Next up, put them in a Pandas DataFrame for ease of access:</p>

<pre><code class="language-python">#   Place into a DataFrame
all_items = zip(id_list, item_list, price_list)
new_prices = pd.DataFrame(list(all_items), columns = ["ID", "Name", "Price"])
</code></pre>

<p>For comparing prices, I'm just being lazy. All I care about is if the price has dropped since the last time I looked. I don't care what the highest or the lowest price is.</p>

<p>I save the prices as a CSV.  The next time the code runs it reads that CSV into a DataFrame called <code>old_prices</code></p>

<pre><code class="language-python">#   Read the old file
if exists("old_prices.csv"):
    old_prices = pd.read_csv("old_prices.csv")
else:
    old_prices = new_prices.copy()
</code></pre>

<p>Now it's a case of iterating through the <em>new</em> prices and comparing each item with its <em>old</em> price.</p>

<p>If the price has dropped, send me a message. If the price of a book is under a quid, I also want to know that as well.</p>

<pre><code class="language-python">#   Compare prices
for id in new_prices["ID"]:
    new_price = new_prices.loc[new_prices["ID"]==id, "Price"].values[0]
    name      = new_prices.loc[new_prices["ID"]==id, "Name" ].values[0]
    #   If a book has recently been added to the wishlist, it won't have an old price
    if id in old_prices.values:
        old_price = old_prices.loc[old_prices["ID"]==id, "Price"].values[0]
        #   Anything less than a quid is good knowing about.
        #   Some prices are ""-Infinity", so check the price is more than zero
        if float(new_price) &lt; 1 and float(new_price) &gt; 0:
            message += (name + "\n£" + str(new_price) + " was £" + str(old_price) + " https://www.amazon.co.uk/dp/"+id + "\n")
        elif float(new_price) &lt; float(old_price) and float(new_price) &gt; 0:
            message += (name + "\n£" + str(new_price) + " was £" + str(old_price) + " https://www.amazon.co.uk/dp/"+id + "\n")

print(message)
</code></pre>

<p>There's a slight wrinkle because some of the prices are <code>-Infinity</code></p>

<blockquote class="social-embed" id="social-embed-1481352496639623169" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/edent" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody">Yay The Semantic Web! <a href="https://x.com/edent/status/1481352496639623169/photo/1">pic.x.com/aY20t5hGoG</a><div class="social-embed-media-grid"><a href="https://pbs.twimg.com/media/FI7R1f-XsAEDVXa.png" class="social-embed-media-link"><img class="social-embed-media" alt="Screenshot of HTML source code. There are several data price attributes with numbers. And one which is negative infinity." src="data:image/webp;base64,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"></a></div></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/1481352496639623169"><span aria-label="11 likes" class="social-embed-meta">❤️ 11</span><span aria-label="2 replies" class="social-embed-meta">💬 2</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2022-01-12T19:48:52.000Z" itemprop="datePublished">19:48 - Wed 12 January 2022</time></a></footer></blockquote>

<p>That's usually when the item is unavailable.</p>

<p>Next, overwrite the <code>old_files.csv</code> with today's prices - we'll use these tomorrow as the old prices.</p>

<pre><code class="language-python">#   Save the Data
new_prices.to_csv('old_prices.csv', index=False)
</code></pre>

<p>Finally, how does the message get sent? It's OK to print something on the console - but I want to get the alerts via email.</p>

<p>This uses <a href="https://docs.python.org/3/library/smtplib.html"><code>smtplib</code></a> to send something via your own SMTP server. You'll need to add your <em>own</em> email server details here!</p>

<pre><code class="language-python">import smtplib
from email.message import EmailMessage

#   Send Email
def send_email(message):
    email_user = 'me@example.com'
    email_password = 'P455w0rd!'
    to = 'you@example.com'
    msg = EmailMessage()
    msg.set_content(message)
    msg['Subject'] = "Today's price drops"
    msg['From'] = email_user
    msg['To'] = to
    server = smtplib.SMTP_SSL('smtp.example.com', 465)
    server.ehlo()
    server.login(email_user, email_password)
    server.send_message(msg)
    server.quit()
</code></pre>

<p>And that's pretty much it! Stick it in a <code>crontab</code> and have it run once per day. Amazon can get a bit funny about screen scraping, so best not to run it too often or you'll hit an IP-based CAPTCHA.</p>

<p>There are a couple of minor annoyances.</p>

<ul>
<li>Some prices fluctuate by pennies. Perhaps you only want to know if the price is lower by more than £1, or more than 10%?</li>
<li>No tracking the lowest price. Do you want to know if it's the lowest price in the last few weeks?</li>
<li>Doesn't automatically buy stuff. It would be nice to just buy a book any time it drops to be lower than a quid.</li>
</ul>

<p>The full code is available on <a href="https://github.com/edent/Amazon-Wishlist-Pricedrop-Alert">github.com/edent/Amazon-Wishlist-Pricedrop-Alert</a>.</p>

<p>Enjoy!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=41673&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2022/01/use-python-to-get-alerted-when-an-amazon-wishlist-item-drops-in-price/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Alexa leaks your private wishlists]]></title>
		<link>https://shkspr.mobi/blog/2021/09/alexa-leaks-your-private-wishlists/</link>
					<comments>https://shkspr.mobi/blog/2021/09/alexa-leaks-your-private-wishlists/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 18 Sep 2021 11:56:33 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[alexa]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[ux]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=40258</guid>

					<description><![CDATA[This morning, my wife noticed that Alexa was insistently flashing its little blue lights.  &#34;Alexa... Notifications?&#34;  &#34;You have one notification. An item on your wishlist has dropped in price. The … is now only £…&#34;  And that&#039;s how my wife found out what I planned to get her for her birthday!  What happened to cause this? I maintain several Amazon Wishlists® of things I want to buy. One of those is…]]></description>
										<content:encoded><![CDATA[<p>This morning, my wife noticed that Alexa was insistently flashing its little blue lights.</p>

<p>"Alexa... Notifications?"</p>

<p>"You have <code>one</code> notification. An item on your wishlist has <code>dropped</code> in price. The <code>…</code> is now only <code>£…</code>"</p>

<p>And that's how my wife found out what I planned to get her for her birthday!</p>

<p>What happened to cause this? I maintain several Amazon Wishlists® of things I want to buy. One of those is for presents I might want to buy my wife - and it is set to <em>private</em>. If you want to buy <em>me</em> a present, you can <a href="https://www.amazon.co.uk/hz/wishlist/ls/13GFCFR2B2IX4?type=wishlist&amp;linkCode=sl2&amp;tag=shksprblogwish-21">view my public wishlist</a>. But my private ones are private to me.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2021/09/List-of-wishlists.png" alt="A list of Wishlists. Liz's presents is marked as private." width="375" height="368" class="aligncenter size-full wp-image-40269">

<p>If you go to edit your wishlist's privacy settings, you'll see this small disclaimer:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2021/09/Manage-your-lists.png" alt="People who access your list will see your recipient name. If you have an Alexa-enabled device, Alexa may alert you when there is a deal for items in your list. Notification Preferences. " width="622" height="187" class="aligncenter size-full wp-image-40261">

<p>Going over to <a href="https://www.amazon.co.uk/alexashopping/notification"></a><a href="https://www.amazon.co.uk/alexashopping/notification">https://www.amazon.co.uk/alexashopping/notification</a> there's this toggle switch.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2021/09/Recommendations.png" alt=" Recommendations and deals  Receive personalised recommendations and deals based on your shopping activity." width="960" height="401" class="aligncenter size-full wp-image-40260">

<p>So, there's <strong>no way</strong> to switch off notifications from private lists. You have to switch them off for everything.</p>

<p>In this case, the harm was minimal. I'll have to find something else as a surprise gift.  But imagine if I had a "private" wishlist for something embarrassing or upsetting? I don't remember ever switching on the option for my Alexa to announce to my entire household that there is a price-drop on my weird fetish.</p>

<p>I've written before about <a href="https://shkspr.mobi/blog/2015/08/anti-social-app-design/">anti-social app design</a>.  The tech bros working on apps often don't consider that people have families. And that they live with people that they want to keep secrets from.</p>

<p>According to the <a href="http://www.ons.gov.uk/ons/rel/family-demography/families-and-households/2014/families-and-households-in-the-uk--2014.html#tab-Household-size">UK's Office of National Statistics</a> - only 28% of households contain a single occupant.  The majority of people <em>live with other people</em>.</p>

<h2 id="what-to-do-next"><a href="https://shkspr.mobi/blog/2021/09/alexa-leaks-your-private-wishlists/#what-to-do-next">What to do next</a></h2>

<p>If you use private wishlists, and have an Alexa, you have a few of options.</p>

<ol>
<li>Stop using Amazon's wishlists, and keep a separate list elsewhere.</li>
<li>Turn off <em>all</em> <a href="https://www.amazon.co.uk/alexashopping/notification">price drop notifications</a>.</li>
<li>Write a ranty blog post and hope a product manage at Amazon takes notice.</li>
</ol>

<h2 id="pre-empting-your-comments"><a href="https://shkspr.mobi/blog/2021/09/alexa-leaks-your-private-wishlists/#pre-empting-your-comments">Pre-empting Your Comments</a></h2>

<p>Before responding to this post, please consider the following:</p>

<h3 id="why-didnt-you-read-the-disclaimer"><a href="https://shkspr.mobi/blog/2021/09/alexa-leaks-your-private-wishlists/#why-didnt-you-read-the-disclaimer">"Why didn't you read the disclaimer?"</a></h3>

<p>I set up this wishlist long before the Alexa was invented. The disclaimer didn't exist then.</p>

<h3 id="you-should-have-gone-through-every-single-option-and-made-sure-you-were-happy"><a href="https://shkspr.mobi/blog/2021/09/alexa-leaks-your-private-wishlists/#you-should-have-gone-through-every-single-option-and-made-sure-you-were-happy">"You should have gone through every single option and made sure you were happy!"</a></h3>

<p>That's unrealistic. Options should be set to preserve privacy by default. Asking the user to go through dozens of different pages of options to prevent their privacy being violated is an unreasonable burden.</p>

<h3 id="this-is-your-fault-for-being-tied-in-to-amazons-ecosystem"><a href="https://shkspr.mobi/blog/2021/09/alexa-leaks-your-private-wishlists/#this-is-your-fault-for-being-tied-in-to-amazons-ecosystem">"This is your fault for being tied in to Amazon's ecosystem!"</a></h3>

<p>Possibly.</p>

<h3 id="jeff-bezos-is-always-listening-to-you1111"><a href="https://shkspr.mobi/blog/2021/09/alexa-leaks-your-private-wishlists/#jeff-bezos-is-always-listening-to-you1111">jEfF BeZoS Is aLwAyS LiStEnInG To yOu!!1!!!!111!</a></h3>

<p>As long as he gives me cheap same-day delivery, IDGAF.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=40258&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2021/09/alexa-leaks-your-private-wishlists/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Synthetic Poetry]]></title>
		<link>https://shkspr.mobi/blog/2021/07/synthetic-poetry/</link>
					<comments>https://shkspr.mobi/blog/2021/07/synthetic-poetry/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 21 Jul 2021 11:48:51 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[tts]]></category>
		<category><![CDATA[turing]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=39605</guid>

					<description><![CDATA[I&#039;ve been experimenting with Amazon&#039;s Polly service. It&#039;s their fancy text-to-sort-of-human-style-speech system.  Think &#34;Alexa&#34; but with a variety of voices, genders, and accents.  Here&#039;s &#34;Brian&#34; - their English, male, received pronunciation voice - reading John Betjeman&#039;s poem &#34;Slough&#34;:  https://shkspr.mobi/blog/wp-content/uploads/2021/07/slough.mp4  The pronunciation of all the words is…]]></description>
										<content:encoded><![CDATA[<p>I've been experimenting with <a href="https://aws.amazon.com/polly/">Amazon's Polly service</a>. It's their fancy text-to-sort-of-human-style-speech system.  Think "Alexa" but with a variety of voices, genders, and accents.</p>

<p>Here's "Brian" - their English, male, received pronunciation voice - reading John Betjeman's poem "<a href="https://en.wikipedia.org/wiki/Slough_(poem)">Slough</a>":</p>

<p></p><div style="width: 324px;" class="wp-video"><video class="wp-video-shortcode" id="video-39605-2" width="324" height="360" preload="metadata" controls="controls"><source type="video/mp4" src="https://shkspr.mobi/blog/wp-content/uploads/2021/07/slough.mp4?_=2"><a href="https://shkspr.mobi/blog/wp-content/uploads/2021/07/slough.mp4">https://shkspr.mobi/blog/wp-content/uploads/2021/07/slough.mp4</a></video></div><p></p>

<p>The pronunciation of all the words is incredibly lifelike. If you heard it on the radio, it might sound like a half-familiar BBC presenter. It has a calm, even tone which suits the poem splendidly.</p>

<p>The rhythm is also spot on. That's mostly a function of the short lines and helpful punctuation the poem contains. Much like iambic pentameter, or a limerick, the syllables lend themselves to a specific and identifiable cadence.</p>

<p>But the emphasis is all wrong. The poem just... ends. There's no sense of finality in the tone.  You'd expect a competent reader to recognise "tinned <em>minds</em>" as being worthy of stressing.  Polly does have some capability to mark specific words for emphasis, but it's all very manual.</p>

<p>There's no synthetic emotion. Do you feel the rage, desperation, sadness, hopelessness of the poem? While <a href="https://docs.aws.amazon.com/polly/latest/dg/supportedtags.html">Polly has some SSML (Speech Synthesis Markup Language) support</a> - the range of emotions it can express are <a href="https://developer.amazon.com/en-US/docs/alexa/custom-skills/speech-synthesis-markup-language-ssml-reference.html#amazon-emotion">severely limited</a>. And, again, must be applied manually.</p>

<h2 id="i-used-to-be-an-adventurer-like-you-but-then-i-took-an-arrow-in-the-knee"><a href="https://shkspr.mobi/blog/2021/07/synthetic-poetry/#i-used-to-be-an-adventurer-like-you-but-then-i-took-an-arrow-in-the-knee">"I used to be an adventurer like you, but then i took an arrow in the knee!"</a></h2>

<p>One of the reasons <a href="https://knowyourmeme.com/memes/i-took-an-arrow-in-the-knee">stock phrases</a> pop up so often in video games is that it is expensive to write and record thousands of different lines of dialogue.</p>

<p>We're <em>almost</em> at a stage where a computer can procedurally generate lines for background characters to speak, and then "record" an audio version in an array of styles. No more expensive voice actors, no more memetic references for in-group homophily. Each player of a game will have a completely different dialogue experience.</p>

<p>But the bit that we're <em>still</em> missing is the automation of emphasis and emotion and comic timing and understatement and... all the things which trained actors spend years learning how to do successfully.</p>

<p>In 2011, the film critic Roger Ebert had surgery which eliminated his voice. He proposed the following <a href="https://bits.blogs.nytimes.com/2011/03/07/roger-ebert-tests-his-vocal-cords-and-comedic-delivery/?src=me&amp;_r=0">"Ebert Test"</a> for synthetic voices:</p>

<blockquote><p>If the computer can successfully tell a joke, and do the timing and delivery, as well as <a href="https://www.youtube.com/watch?v=y-LD9Xgqf6w">Henny Youngman</a>, then that’s the voice I want.
</p></blockquote>

<p>We're <em>so</em> close, I can taste it.   The Turing Test for realistic voices is whether they can move the audience to tears with poetry.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=39605&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2021/07/synthetic-poetry/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		<enclosure url="https://shkspr.mobi/blog/wp-content/uploads/2021/07/slough.mp4" length="1586486" type="video/mp4" />

			</item>
		<item>
		<title><![CDATA[Bug report: 4K iPlayer on the Amazon Fire Stick]]></title>
		<link>https://shkspr.mobi/blog/2020/01/bug-report-4k-iplayer-on-the-amazon-fire-stick/</link>
					<comments>https://shkspr.mobi/blog/2020/01/bug-report-4k-iplayer-on-the-amazon-fire-stick/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 29 Jan 2020 12:14:30 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[BBC]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[hdmi]]></category>
		<category><![CDATA[iplayer]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=33818</guid>

					<description><![CDATA[Technology never works right. And video technology never works right even harder.  The Amazon 4K Fire Stick is a pretty cool bit of kit. It&#039;s an Android device which can push 4K HDR video with surround sound to your TV. But, like any technology, it&#039;s buggy. Here&#039;s the bug report I&#039;ve tried to send to Amazon and the BBC. They haven&#039;t answered - so I&#039;m publishing it here as well.  BBC iPlayer…]]></description>
										<content:encoded><![CDATA[<p>Technology never works right. And video technology never works right even harder.</p>

<p>The Amazon 4K Fire Stick is a pretty cool bit of kit. It's an Android device which can push 4K HDR video with surround sound to your TV. But, like any technology, it's buggy. Here's the bug report I've tried to send to Amazon and the BBC. They haven't answered - so I'm publishing it here as well.</p>

<p>BBC iPlayer supplies 4K video - but the app doesn't switch to 4K mode, it stays at 1080p.</p>

<h2 id="amazon-debug"><a href="https://shkspr.mobi/blog/2020/01/bug-report-4k-iplayer-on-the-amazon-fire-stick/#amazon-debug">Amazon debug</a></h2>

<p>To turn on the Fire stick's debug mode - and get access to X-Ray - <a href="https://developer.amazon.com/docs/fire-tv/system-xray.html">follow these instructions</a>.</p>

<p>This lets you see the bandwidth being used, HDCP information, and audio/video information.  Here's a 4K presentation via Amazon's own video player.
<img src="https://shkspr.mobi/blog/wp-content/uploads/2020/01/Amazon-4K.jpg" alt="Amazon video with debug information" width="1024" height="560" class="aligncenter size-full wp-image-33823">
In the top left is the HDMI output information and bandwidth stats. On the right is the video codec data.</p>

<h2 id="iplayer"><a href="https://shkspr.mobi/blog/2020/01/bug-report-4k-iplayer-on-the-amazon-fire-stick/#iplayer">iPlayer</a></h2>

<p>Within iPlayer you can opt-in to the beta programme, this gives you access to 4K content.  But let's take a look at the debug information.
<img src="https://shkspr.mobi/blog/wp-content/uploads/2020/01/iPlayer-Bug.jpg" alt="BBC video with debug information on it." width="1024" height="576" class="aligncenter size-full wp-image-33820">
4K video <em>is</em> being streamed at 25fps.  But if we look in the top left corner, the app hasn't switched out of 1080p @ 60fps.
<img src="https://shkspr.mobi/blog/wp-content/uploads/2020/01/iPlayer-1080p.jpg" alt="iPlayer output at 1080p." width="1024" height="456" class="aligncenter size-full wp-image-33821"></p>

<p><img src="https://shkspr.mobi/blog/wp-content/uploads/2020/01/iPlayer-4K-detail.jpg" alt="iPlayer detail showing 4K." width="640" height="739" class="aligncenter size-full wp-image-33822">
The end result is a juddering rescaled mess.</p>

<p>So, if you or a friend works for either Amazon or the BBC, please ask them to take a look, eh?</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=33818&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2020/01/bug-report-4k-iplayer-on-the-amazon-fire-stick/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Amazon Prime Video's weird Unicode problems]]></title>
		<link>https://shkspr.mobi/blog/2019/01/amazon-prime-videos-weird-unidcode-problems/</link>
					<comments>https://shkspr.mobi/blog/2019/01/amazon-prime-videos-weird-unidcode-problems/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 25 Jan 2019 12:19:14 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[unicode]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=31255</guid>

					<description><![CDATA[It&#039;s 2019 and high-tech devices are still plagued by text encoding bugs.  I recently bought the new 4K Amazon Fire Stick. It&#039;s a little Android dongle which plays videos. It&#039;s neat - but quite often displays weird text errors.  Take the kids&#039; TV show House of Anubis, the Fire displays the description like this:   Looking at the source code for the description:   That&#039;s the character &#34;private use…]]></description>
										<content:encoded><![CDATA[<p>It's 2019 and high-tech devices are still plagued by text encoding bugs.</p>

<p>I recently bought the new 4K Amazon Fire Stick. It's a little Android dongle which plays videos. It's neat - but quite often displays weird text errors.</p>

<p>Take the kids' TV show <a href="https://amzn.to/2W5R7Y7">House of Anubis</a>, the Fire displays the description like this:
<img src="https://shkspr.mobi/blog/wp-content/uploads/2019/01/House-of-Anubis.jpg" alt="A description of a TV show - there are some weird blank characters on screen." width="1024" height="768" class="aligncenter size-full wp-image-31256"></p>

<p>Looking at the source code for the description:
<img src="https://shkspr.mobi/blog/wp-content/uploads/2019/01/Source-of-of-Amazon-Prime-page-fs8.png" alt="Welcome to Anubis House. It is at this boarding school that students begin settling in for the academic year only to find one student missing, a secret panel in the houses attic, codes leading to backroom staircases, clandestine rituals, and more!" width="841" height="468" class="aligncenter size-full wp-image-31257"></p>

<p>That's the character "<a href="https://en.wikipedia.org/wiki/Private_Use_Areas">private use</a> two" (U+0092).  What on earth is that doing there?</p>

<p>Well, in the ancient <a href="https://en.wikipedia.org/wiki/Windows-1252">Windows-1252</a> encoding, <code>0x92</code> is <code>’</code> - the curly quote. It looks like someone has tried to write "in the house’s attic" on an old Windows machine, Amazon have ingested the data thinking it was Unicode, and displayed an error!</p>

<p>Here's "<a href="https://amzn.to/4jwNy80">Young Sheldon</a>":</p>

<p><a href="https://amzn.to/4jwNy80"><img src="https://shkspr.mobi/blog/wp-content/uploads/2019/01/Young-Sheldon.jpeg" alt="Description with an error in it." width="1024" height="447" class="aligncenter size-full wp-image-31258"></a></p>

<p>How does the word "isn't" become "isnâ€™t"?  There's <a href="https://www.justinweiss.com/articles/how-to-get-from-theyre-to-theyre/">a great explanation from Justin Weiss</a>, basically:</p>

<ul>
<li>Unicode <code>’</code> (U+2019) contains 3 bytes - <code>0xE2 0x80 0x99</code></li>
<li>When those three bytes are converted to Windows-1252, they become â € ™</li>
</ul>

<p>The Android version of Prime video goes a step further:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2019/01/Sheldon-on-Android.png" alt="Screenshot of the same text on Android. An additional error has crept in." width="720" height="565" class="aligncenter size-full wp-image-31282">

<p>The Euro Symbol has been converted into its HTML entity <code>&amp;#x20AC;</code></p>

<p>There are <a href="https://www.google.com/search?q=%C3%A2%E2%82%ACTM+season+video+site%3Awww.amazon.co.uk">hundreds of examples</a> of video descriptions being mangled like this.</p>

<p>And, occasionally, you find this hot mess:
<a href="https://amzn.to/2Dmw1x7"><img src="https://shkspr.mobi/blog/wp-content/uploads/2019/01/Weird-encoding-fs8.png" alt="" width="973" height="407" class="aligncenter size-full wp-image-31263"></a>
<img src="https://shkspr.mobi/blog/wp-content/uploads/2019/01/Samt.jpg" alt="Dozens of weird characters on screen." width="1024" height="696" class="aligncenter size-full wp-image-31265">
What's going on?</p>

<h2 id="two-countries-separated-by-a-common-language"><a href="https://shkspr.mobi/blog/2019/01/amazon-prime-videos-weird-unidcode-problems/#two-countries-separated-by-a-common-language">Two countries separated by a common language</a></h2>

<p>Except, of course, this doesn't happen on the American version of Amazon Prime Video.</p>

<p>Here's the description of <a href="https://www.amazon.com/Gotham-2016-Comic-Con-Panel/dp/B01KU8SJ9A/">Gotham S03</a> from Amazon USA:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2019/01/American-Gotham-fs8.png" alt="Screencap from the American version. All the text is pristine." width="966" height="436" class="aligncenter size-full wp-image-31260">

<p>Once the text gets to this side of the pond, it goes horribly wrong.
<a href="https://amzn.to/2T67hi0"><img src="https://shkspr.mobi/blog/wp-content/uploads/2019/01/UK-Gotham-fs8.png" alt="Screencap showing the description text from the UK. It is mangled." width="966" height="436" class="aligncenter size-full wp-image-31259"></a></p>

<p>As well as the <code>â€TM</code> issue, there's another new snag.  The hyphen is actually <code>-</code> hyphen-minus (U+002D). Something in Amazon's conversion process is transforming that to <code>–</code> en dash (U+2013).</p>

<p>That then gets <a href="https://www.i18nqa.com/debug/utf8-debug.html">buggily encoded</a> to â€".</p>

<p>I've reported these errors to my friends at Amazon - they are in the process of correcting them.</p>

<p>You can <a href="https://amzn.to/2S3iO4I">buy the Amazon Fire TV Stick 4K Ultra HD</a> for just Â£50.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=31255&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2019/01/amazon-prime-videos-weird-unidcode-problems/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Solar Battery and Alexa - in 30 lines of code]]></title>
		<link>https://shkspr.mobi/blog/2017/11/solar-battery-and-alexa-in-30-lines-of-code/</link>
					<comments>https://shkspr.mobi/blog/2017/11/solar-battery-and-alexa-in-30-lines-of-code/#respond</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 04 Nov 2017 10:38:49 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[alexa]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[battery]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[NaBloPoMo]]></category>
		<category><![CDATA[solar]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=28636</guid>

					<description><![CDATA[Amazon Alexa is a fun little bit of kit. But it can be tricky getting it to work with all your smart devices.  Not every company has an Alexa skill - just like not every company has an app.  Using Flask-Ask it is possible to bring Alexa smarts to a range of previously mute devices.  Alexa coding works on &#34;intents&#34; - the following is a simple intent. That is, you can only ask the skill one…]]></description>
										<content:encoded><![CDATA[<iframe title="Moixa Battery and Amazon Echo" width="620" height="349" src="https://www.youtube.com/embed/RpQqaFPbxsA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>

<p>Amazon Alexa is a fun little bit of kit. But it can be tricky getting it to work with all your smart devices.  Not every company has an Alexa skill - just like not every company has an app.</p>

<p>Using <a href="https://github.com/johnwheeler/flask-ask">Flask-Ask</a> it is possible to bring Alexa smarts to a range of previously mute devices.</p>

<p>Alexa coding works on "intents" - the following is a simple intent. That is, you can only ask the skill one thing.  No state is maintained, no multiple commands to get right, no complexity.  This gets information from a single source and speaks it.</p>

<h2 id="code"><a href="https://shkspr.mobi/blog/2017/11/solar-battery-and-alexa-in-30-lines-of-code/#code">Code</a></h2>

<p>The basic Python is pretty simple and can be adapted to query almost any basic JSON API.  Let me walk you through it.</p>

<p>All the boilerplate needed to set up the skill:</p>

<pre>import logging
from operator import itemgetter

import requests
from flask import Flask
from flask_ask import Ask, statement

app = Flask(__name__)
ask = Ask(app, '/')
logger = logging.getLogger()

@ask.launch
def launch():
    return stats()
</pre>

<p>The API that you want to call. This is a basic JSON API which doesn't require authentication.</p>

<pre>ENDPOINT = "https://example.com/api/maslow.json"
</pre>

<p>Here's the main part of the Skill.  When the intent is triggered, call the API.  Get the data and format it for speech.  If there was an error, tell the user.</p>

<p>Make sure that the name of the intent is <em>identical</em> to the one you set up in the Alexa Developer console.</p>

<pre>@ask.intent("BatteryIntent")
def stats():
    r = requests.get(ENDPOINT)
    data = r.json()

    if r.status_code == 200:
        percent = data['battery/amphours']
        speech = "Your Moixa battery is at " + str(int(round(percent))) + " percent capacity right now."
    else:
        speech = "There was a problem connecting to the battery."

    logger.info('speech = {}'.format(speech))
    return statement(speech)
</pre>

<p>Short and easy.</p>

<h2 id="deploying"><a href="https://shkspr.mobi/blog/2017/11/solar-battery-and-alexa-in-30-lines-of-code/#deploying">Deploying</a></h2>

<p>Again, Amazon don't make it easy to deploy Alexa skills - here's <a href="https://developer.amazon.com/blogs/alexa/post/8e8ad73a-99e9-4c0f-a7b3-60f92287b0bf/new-alexa-tutorial-deploy-flask-ask-skills-to-aws-lambda-with-zappa">a guide to getting started using Zappa</a>.</p>

<p>Remember, Alexa is <em>not</em> AI. You must painstakingly type in all the "utterances" that you think your users might say to activate the skill.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/09/Alexa-Utterances-fs8.png" alt="A list of phrases used to activate the device" width="820" height="311" class="aligncenter size-full wp-image-28639">

<h2 id="problems"><a href="https://shkspr.mobi/blog/2017/11/solar-battery-and-alexa-in-30-lines-of-code/#problems">Problems</a></h2>

<p>There is one major problem with retrofitting Alexa skills.</p>

<p>Lots of Internet connected devices have no ability to log in remotely - and certainly don't have the OAuth systems that Amazon demands.  Alexa has no ability to directly connect to IP addresses on its own subnets.</p>

<p>This means most skills will need hard-coded credentials - and a way to traverse into your network.</p>

<p>In short, this means means they can't be shared on the Amazon store.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=28636&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2017/11/solar-battery-and-alexa-in-30-lines-of-code/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Alexa - what bin day is it?]]></title>
		<link>https://shkspr.mobi/blog/2017/07/alexa-what-bin-day-is-it/</link>
					<comments>https://shkspr.mobi/blog/2017/07/alexa-what-bin-day-is-it/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 04 Jul 2017 11:05:02 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[alexa]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[council]]></category>
		<category><![CDATA[Open Data]]></category>
		<category><![CDATA[oxford]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=25465</guid>

					<description><![CDATA[Bin day is the most magical time of the week! Children of all ages cry &#34;Which bins is it?! Oh! Which bins?&#34;    Is today recycling day? Or green waste day? Or humble landfill day? Should my food caddy go out? Gosh! Who can keep track?  I mean, obviously I could look at my calendar. Or sign up for free SMS alert. Or use push notifications in their app. But where&#039;s the fun in that?  &#34;Alexa...&#34;   …]]></description>
										<content:encoded><![CDATA[<p>Bin day is the most magical time of the week! Children of all ages cry "Which bins is it?! Oh! Which bins?"</p>

<p><a href="https://www.flickr.com/photos/dave-goodman/3609172860/"><img src="https://shkspr.mobi/blog/wp-content/uploads/2017/07/Row-of-recycling-bins.jpg" alt="Row of recycling bins - photo by  Dave Goodman" width="1024" height="480" class="aligncenter size-full wp-image-25468"></a></p>

<p>Is today recycling day? Or green waste day? Or humble landfill day? Should my food caddy go out? Gosh! Who can keep track?  I mean, obviously I could look at my calendar. Or <a href="https://www.oxford.gov.uk/info/20250/bins/162/bin_collection_reminders">sign up for free SMS alert</a>. Or use push notifications in <a href="https://play.google.com/store/apps/details?id=com.cloud9technologies.oxford">their app</a>. But where's the fun in that?</p>

<p>"<a href="https://amzn.to/2tLmlJ3">Alexa</a>..."</p>

<video width="640" height="360" controls="" src="https://shkspr.mobi/blog/wp-content/uploads/2017/07/Oxford-Bins-97dQbkuQtUM.mp4">

<p>The code I've written uses Oxford City Council's civic data APIs - which will deal with bank holidays and other issues.</p>

<p>I've written before on <a href="https://shkspr.mobi/blog/2017/07/uk-flood-forecast-on-amazon-alexa/">how to build a Flash Briefing skill</a>.  You just need to host a scrap of JSON somewhere. In this case:</p>

<pre><code>{
  "uid": "https://example.com/bins/",
  "updateDate": "2017-07-04T00:00:00+01:00",
  "titleText": "Bins",
  "mainText": "Today's bin collection is Green Refuse Bins and Food Caddies",
  "redirectionUrl": "https://www.oxford.gov.uk/homepage/154/find_your_bin_collection_day"
}
</code></pre>

<h2 id="why-im-not-releasing-this-skill-to-the-public"><a href="https://shkspr.mobi/blog/2017/07/alexa-what-bin-day-is-it/#why-im-not-releasing-this-skill-to-the-public">Why I'm not releasing this skill to the public</a></h2>

<p>There's no <em>official</em> API yet.  I am using some... errr... "borrowed" credentials I found inside the official <a href="https://play.google.com/store/apps/details?id=com.cloud9technologies.oxford">Oxford City Council app</a>.  I'm chatting to someone at the council to see if there's a more official route I can take.</p>

<p><ins datetime="2017-07-05T14:03:52+00:00">Update! I'm delighted to say that there <em>is</em> an <strong>open</strong> API! Details at the end.</ins></p>

<p>Secondly, I'm afraid of handling personal data. The bins API requires a home's UPRN - <a href="https://www.ordnancesurvey.co.uk/about/news/2015/uprn-release-sharing-location-data.html">Unique Property Reference Number</a>.  Most people don't know their number, which means I'd need to integrate address lookup into the system. That would mean I would know which of my neighbours has purchased an Amazon Echo.</p>

<p>I'd also have to store that data, process it, and generally have to comply with data protection laws.  Which is a bit of a faff for a five-minute project.</p>

<h2 id="code"><a href="https://shkspr.mobi/blog/2017/07/alexa-what-bin-day-is-it/#code">Code</a></h2>

<p>If you have access to the API, you can run this PHP code and set up your own Alexa skill.</p>

<p>For postcode to UPRN lookups:</p>

<pre><code>https://apps.cloud9technologies.com/oxford/citizenmobile/openapi/addresses?postcode=OX1%203HZ
</code></pre>

<p>For bin lookups (last value is the UPRN):</p>

<pre><code>https://apps.cloud9technologies.com/oxford/citizenmobile/openapi/wastecollections/200004675068
</code></pre>

<p><strong>WARNING</strong> this really is a scrap of code that I threw together early on a Tuesday morning. No guarantees of style, substance, or efficacy.  Released under the <a href="https://opensource.org/licenses/MIT">MIT License</a></p>

<pre><code>&lt;?php

$wasteURL = "https://apps.cloud9technologies.com/oxford/citizenmobile/openapi/wastecollections/";
$uprn = "";

//  Get the data
$data = file_get_contents($wasteURL . $uprn);

//  Data is in JSON
$json = json_decode($data, true);

//  Strip out unneeded elements
unset($json["WasteCollectionDates"]["UPRN"]);

//  An array to hold the collection information
$collections = array ();

//  Loop through the array
//  Store the data as timestamp=&gt;bins
foreach ($json["WasteCollectionDates"] as $key =&gt; $value) {
    $details =  $value["ContainerDescription"];
    $date = strtotime($value["CollectionDate"]);
    if ($collections[$date] != null)
    {
        //  Multiple bins can be collected each day
        $details = " and " . $details;
    }

    //  Ignore empty elements
    if ($date != null)
    {
        $collections[$date] .= $details;
    }
}

//  Date order the array
ksort($collections);
//  Place pointer at the start of array
reset($collections);

//  The array key is a UNIX timestamp
$first_date = key($collections);
$first_bins = $collections[$first_date];

//  Is the next bin collection today, tomorrow, or further in the future?
//  https://stackoverflow.com/a/25623230/1127699
$today = new DateTime(); // This object represents current date/time

$today-&gt;setTime( 0, 0, 0 ); // reset time part, to prevent partial comparison

//  Get the timezone as the bins API doesn't return it
$timezone = $today-&gt;getTimezone();

//  What is the date of the next bin collection?
$match_date = DateTime::createFromFormat("U", $first_date);
//  Set the timezone based on the local time
$match_date-&gt;setTimezone($timezone);
$match_date-&gt;setTime( 0, 0, 0 ); // reset time part, to prevent partial comparison

$diff = $today-&gt;diff( $match_date );
$diffDays = (integer)$diff-&gt;format( "%R%a" ); // Extract days count in interval

$headline = "";

switch( $diffDays ) {
    case 0:
        $headline = "Today's bin collection is " . $first_bins;
        break;
    case +1:
        $headline = "Tomorrow's bin collection is " . $first_bins;
        break;
    default:
        $headline = "The next bin collection is " . $first_bins . " on ". $match_date-&gt;format('l');
}

//  Set the correct header for JSON data
header('Content-Type: application/json');
?&gt;{
  "uid": "https://example.com/bins/",
  "updateDate": "&lt;?php echo $today-&gt;format(DateTime::ATOM); ?&gt;",
  "titleText": "Bins",
  "mainText": "&lt;?php echo $headline; ?&gt;",
  "redirectionUrl": "https://www.oxford.gov.uk/homepage/154/find_your_bin_collection_day"
}
</code></pre>

<h2 id="thanks"><a href="https://shkspr.mobi/blog/2017/07/alexa-what-bin-day-is-it/#thanks">Thanks!</a></h2>

<p>If you've enjoyed this post, please leave a comment or you can <a href="https://www.amazon.co.uk/gp/registry/wishlist/ref=cm_wl_search_1?ie=UTF8&amp;cid=A327FR3Q472EBX&amp;tag=shksprblogwish-21">get me something from my Amazon wishlist</a></p>
</video><img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=25465&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2017/07/alexa-what-bin-day-is-it/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[UK Flood Forecast on Amazon Alexa]]></title>
		<link>https://shkspr.mobi/blog/2017/07/uk-flood-forecast-on-amazon-alexa/</link>
					<comments>https://shkspr.mobi/blog/2017/07/uk-flood-forecast-on-amazon-alexa/#respond</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 03 Jul 2017 11:26:15 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[alexa]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[Open Data]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=25456</guid>

					<description><![CDATA[You can now get the UK&#039;s flood forecast as part of your Flash Briefing on Amazon&#039;s Alexa.        I&#039;ve tried previously to create an interactive Alexa skill - it did not go well.  This time, I thought I&#039;d create an easier skill - a Flash Briefing.  You ask Alexa for your daily news report and it reads out items that you&#039;ve configured - news, weather, traffic, that sort of thing.  For a basic…]]></description>
										<content:encoded><![CDATA[<p>You can now get the <a href="https://www.amazon.co.uk/dp/B073NQC1PS/">UK's flood forecast as part of your Flash Briefing on Amazon's Alexa</a>.</p>

<video width="640" height="360" controls="">
  <source src="https://shkspr.mobi/blog/wp-content/uploads/2017/07/UK-Flood-Forecast-on-Amazon-Alexa-VNuprGcdea8.mp4" type="video/mp4">
</video>

<p>I've tried previously to create an interactive Alexa skill - <a href="https://shkspr.mobi/blog/2017/05/amazon-alexa-and-solar-panels/">it did not go well</a>.  This time, I thought I'd create an easier skill - a Flash Briefing.  You ask Alexa for your daily news report and it reads out items that you've configured - news, weather, traffic, that sort of thing.</p>

<p>For a basic skill, all you need is a tiny scrap of JSON.  In this case:</p>

<pre><code>{
  "uid": "https://example.com/flood/index.php",
  "updateDate": "2017-07-02T09:30:00Z",
  "titleText": "UK Flood Forecast",
  "mainText": "The overall flood risk is VERY LOW for the next five days. Minor surface water flooding impacts are possible, but not expected, on Thursday.",
  "redirectionUrl": "https://flood-warning-information.service.gov.uk/"
}
</code></pre>

<p>If you can dynamically generate something like that, and host it on a website, you can make a skill.</p>

<p>Following the <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/steps-to-create-a-flash-briefing-skill">Amazon</a> <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/flash-briefing-skill-api-feed-reference">process</a> is <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/tips-for-creating-a-great-flash-briefing-skill">slightly</a> <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/understanding-the-flash-briefing-skill-api">tedious</a> - especially when it gives you errors like this.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/07/Amazon-Alexa-error.jpg" alt="An error message just says &quot;There is an error parsing the feed&quot;" width="672" height="170" class="aligncenter size-full wp-image-25457">

<p>Pro Tip - tell your users why and where something has failed. They can't be expected to magically guess what the problem is.</p>

<p>You can beta test a skill before it goes live.  The submission and review process was painless - took about 12 hours on a weekend.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/07/Amazon-skill-submission.jpg" alt="A skill submission form" width="605" height="207" class="aligncenter size-full wp-image-25458">

<h2 id="voice-interfaces-for-government"><a href="https://shkspr.mobi/blog/2017/07/uk-flood-forecast-on-amazon-alexa/#voice-interfaces-for-government">Voice Interfaces For Government</a></h2>

<p>(My thoughts - not <a href="https://shkspr.mobi/blog/2016/11/newvember-new-job/">my employer</a>'s)</p>

<p>This is an <em>unofficial</em> service that I've built using the <a href="https://environment.data.gov.uk/flood-monitoring/doc/reference">Open Data produced by my friends at the environment agency</a>.</p>

<p>In an ideal world, you wouldn't need to create specific skills like this. Nor would you have to create a specially formatted file for every voice assistant out there.  Websites would be full of semantic markup and intelligent assistants would be easily able to work out when the council offices were open, which bus routes were delayed, and what the flood risk was.</p>

<p>We're not there yet.</p>

<p>There is a <em>huge</em> industry push towards voice interfaces.  Is it incumbent on Government to create services like this, or is it enough to create APIs and let others build things?</p>

<p>There's a <a href="https://gds.blog.gov.uk/2013/03/12/were-not-appy-not-appy-at-all/">long-standing moratorium on the UK Government creating mobile apps</a> - we can't waste money developing for a dozen different platforms, keeping them updated, reacting to changing requirements from store owners.</p>

<p>Is the same true for voice interfaces?  Siri, Cortana, Alexa, whatever Google's one is called, Bixby, and a dozen more round the corner. Each needing a different configuration to get them to vocalise your news. Each needing you to sign up to yet-another developer agreement.</p>

<p>My job is looking at open standards. We're too early in this industry to converge on one-standard-to-rule-them all. But if Voice is The Future™, we all need to think about how we make it as easy to deploy interactive speech services as possible.</p>

<p>Voice feels like it <em>could</em> be something - but only if it is open to all.</p>

<hr>

<p>You can install the <a href="https://www.amazon.co.uk/dp/B073NQC1PS/">UK's flood forecast on Amazon's Alexa</a>.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=25456&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2017/07/uk-flood-forecast-on-amazon-alexa/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Amazon Alexa and Solar Panels]]></title>
		<link>https://shkspr.mobi/blog/2017/05/amazon-alexa-and-solar-panels/</link>
					<comments>https://shkspr.mobi/blog/2017/05/amazon-alexa-and-solar-panels/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 03 May 2017 17:54:22 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[alexa]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[developer]]></category>
		<category><![CDATA[HowTo]]></category>
		<category><![CDATA[solar]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=25136</guid>

					<description><![CDATA[I can now query my solar panels via my Alexa Amazon Dot Echo thingie (why so many names?).  https://shkspr.mobi/blog/wp-content/uploads/2017/05/VID_20170501_161804.webm  I flatter myself as a reasonably competent techie and programmer, but fuck me AWS Lambdas and Alexa skills are a right pile of shite!  Sorry if that sounds a bit harsh, but they&#039;re a pain in the arse to get anything done.  I…]]></description>
										<content:encoded><![CDATA[<p>I can now query my solar panels via my Alexa Amazon Dot Echo thingie (why so many names?).</p>

<p></p><div style="width: 620px;" class="wp-video"><video class="wp-video-shortcode" id="video-25136-4" width="620" height="349" preload="metadata" controls="controls"><source type="video/webm" src="https://shkspr.mobi/blog/wp-content/uploads/2017/05/VID_20170501_161804.webm?_=4"><a href="https://shkspr.mobi/blog/wp-content/uploads/2017/05/VID_20170501_161804.webm">https://shkspr.mobi/blog/wp-content/uploads/2017/05/VID_20170501_161804.webm</a></video></div><p></p>

<p>I flatter myself as a reasonably competent techie and programmer, but fuck me AWS Lambdas and Alexa skills are a right pile of shite!  Sorry if that sounds a bit harsh, but they're a pain in the arse to get anything done.</p>

<p>I wanted something simple.  When I say "Solar Panels", call this API, then say this phrase.  That's the kind of thing which <em>should</em> take 5 minutes in something like IFTTT.  Instead, it took around two hours of following out-of-date official tutorials, and whinging on Twitter, before I got my basic service up and running.</p>

<p>A quick bit of preparatory searching on Alta Vista 2.0 and I'd got incredibly frustrated.</p>

<blockquote class="social-embed" id="social-embed-858917427081613312" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/edent" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody">Does anyone have an EASY tutorial for Alexa skills?<br>As in, not 27 steps where step 5 just says "install node" &amp; 26 says "see other tutorial"</section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/858917427081613312"><span aria-label="6 likes" class="social-embed-meta">❤️ 6</span><span aria-label="9 replies" class="social-embed-meta">💬 9</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2017-05-01T05:34:07.000Z" itemprop="datePublished">05:34 - Mon 01 May 2017</time></a></footer></blockquote>

<p>I ended up following this "easy" <a href="https://web.archive.org/web/20170516010425/https://developer.amazon.com/alexa-skills-kit/alexa-skill-quick-start-tutorial"><strong>30</strong> step guide to develop a basic skill</a>.</p>

<p>It's not so bad, but it does reveal Amazon's contempt for developers. Several of the steps contained errors, it involves multiple logins, random clicks, and a bunch of copy &amp; pasting. Dull and complex.</p>

<blockquote class="social-embed" id="social-embed-859030859717935104" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><blockquote class="social-embed" id="social-embed-859029576810467328" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/edent" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody"><small class="social-embed-reply"><a href="https://twitter.com/edent/status/859028437171920898">Replying to @edent</a></small>Brilliant! AWS picked up the wrong address from my Amazon UK account. How?<br>It also wouldn't copy across my credit card details! Why?</section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/859029576810467328"><span aria-label="0 likes" class="social-embed-meta">❤️ 0</span><span aria-label="0 replies" class="social-embed-meta">💬 0</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2017-05-01T12:59:45.000Z" itemprop="datePublished">12:59 - Mon 01 May 2017</time></a></footer></blockquote><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/edent" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody"><small class="social-embed-reply"><a href="https://twitter.com/edent/status/859029576810467328">Replying to @edent</a></small>The cloud is everywhere!<br>The cloud is nowhere!<br>The cloud loves you!<br>The cloud knows all!<br>The cloud only works in specific US locations! <a href="https://twitter.com/edent/status/859030859717935104/photo/1">pic.x.com/15dibbda0v</a><div class="social-embed-media-grid"><a href="https://pbs.twimg.com/media/C-vkA2oWsAEK2iW.jpg" class="social-embed-media-link"><img class="social-embed-media" alt="" src="data:image/webp;base64,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"></a></div></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/859030859717935104"><span aria-label="2 likes" class="social-embed-meta">❤️ 2</span><span aria-label="1 replies" class="social-embed-meta">💬 1</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2017-05-01T13:04:51.000Z" itemprop="datePublished">13:04 - Mon 01 May 2017</time></a></footer></blockquote>

<p>A frustrating and ultimately unsatisfying experience.  I ended up using StackOverflow to correct errors in my code because the documentation was so woefully lacking.</p>

<h2 id="the-code"><a href="https://shkspr.mobi/blog/2017/05/amazon-alexa-and-solar-panels/#the-code">The Code</a></h2>

<p>The Python is convoluted, but manageable.  When it hears the trigger phrase it opens a JSON API, extracts a result, then speaks it.  It's mostly scaffolding.  This is based on the example code. I've removed the comments.</p>

<pre><code class="language-python">from __future__ import print_function
import json, requests

# --------------- Helpers that build all of the responses ----------------------
def build_speechlet_response(title, output, reprompt_text, should_end_session):
    return {
        'outputSpeech': {
            'type': 'PlainText',
            'text': output
        },
        'card': {
            'type': 'Simple',
            'title': "SessionSpeechlet - " + title,
            'content': "SessionSpeechlet - " + output
        },
        'reprompt': {
            'outputSpeech': {
                'type': 'PlainText',
                'text': reprompt_text
            }
        },
        'shouldEndSession': should_end_session
    }


def build_response(session_attributes, speechlet_response):
    return {
        'version': '1.0',
        'sessionAttributes': session_attributes,
        'response': speechlet_response
    }

# --------------- Functions that control the skill's behavior ------------------
def get_welcome_response():
    API_url = 'https://example.com/'
    response = requests.get(url=API_url)
    data = json.loads(response.text)
    watts = data['Body']['Data']['PAC']['Values']['Result']
    session_attributes = {}
    card_title = "Welcome"
    speech_output = "Your Solar Panels are generating " + str(watts) + " watts right now."
    reprompt_text = ""
    should_end_session = True
    return build_response(session_attributes, build_speechlet_response(
        card_title, speech_output, reprompt_text, should_end_session))

def handle_session_end_request():
    card_title = "Session Ended"
    speech_output = "May your day be sunny and bright! "
    should_end_session = True
    return build_response({}, build_speechlet_response(
        card_title, speech_output, None, should_end_session))

# --------------- Events ------------------
def on_session_started(session_started_request, session):
    print("on_session_started requestId=" + session_started_request['requestId']
          + ", sessionId=" + session['sessionId'])

def on_launch(launch_request, session):
    print("on_launch requestId=" + launch_request['requestId'] +
          ", sessionId=" + session['sessionId'])
    return get_welcome_response()

def on_intent(intent_request, session):
    print("on_intent requestId=" + intent_request['requestId'] +
          ", sessionId=" + session['sessionId'])
    intent = intent_request['intent']
    intent_name = intent_request['intent']['name']

def on_session_ended(session_ended_request, session):
    print("on_session_ended requestId=" + session_ended_request['requestId'] +
          ", sessionId=" + session['sessionId'])

# --------------- Main handler ------------------
def lambda_handler(event, context):
    print("event.session.application.applicationId=" +
          event['session']['application']['applicationId'])
    if event['session']['new']:
        on_session_started({'requestId': event['request']['requestId']},
                           event['session'])
    if event['request']['type'] == "LaunchRequest":
        return on_launch(event['request'], event['session'])
    elif event['request']['type'] == "IntentRequest":
        return on_intent(event['request'], event['session'])
    elif event['request']['type'] == "SessionEndedRequest":
        return on_session_ended(event['request'], event['session'])
</code></pre>

<h2 id="this-is-not-ai"><a href="https://shkspr.mobi/blog/2017/05/amazon-alexa-and-solar-panels/#this-is-not-ai">This is <em>not</em> AI</a></h2>

<p>I kinda thought that Amazon would hear "solar panels" and work out the rest of the query using fancy neural network magic. Nothing could be further from the truth. The developer has to manually code <em>every single possible permutation</em> of the phrase that they expect to hear.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/05/Favourite-Colour-fs8.png" alt="A listing of every possible subject object verb combination" width="447" height="552" class="aligncenter size-full wp-image-25142">

<p>This isn't AI. Voice interfaces are the command line. But you don't get tab-to-complete.</p>

<p>Amazon allow you to test your code by typing rather than speaking. I spent a frustrating 10 minutes trying to work out why my example code didn't work. Want to know why? I was typing "favo<em>u</em>rite" rather than the American spelling.  Big Data my shiny metal arse.</p>

<h2 id="why-not-iftt"><a href="https://shkspr.mobi/blog/2017/05/amazon-alexa-and-solar-panels/#why-not-iftt">Why not IFTT?</a></h2>

<p>So, there <em>is</em> an official <a href="https://web.archive.org/web/20200924202817/https://twitter.com/sammachin/status/859125475498758145?ref_src=twsrc%5Etfw">If-This-Then-That channel for Alexa</a>.</p>

<p>But like most IFTTT services, it isn't well supported by the company. It works with a few blessed services, but you can't bring in your own APIs, nor define your own responses.</p>

<p>It is barely tested and has all sorts of weird restrictions.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/05/ifttt-fs8.png" alt="The If-This-Then-That service only works with lower case characters" width="619" height="619" class="aligncenter size-full wp-image-25140">

<p>Here's a tip, gang, if your service can't cope with upper-case characters that means it isn't ready to release to the public.</p>

<p>The founder of <a href="https://web.archive.org/web/20170523171047/https://www.sayspring.com/">SaySpring</a> recommended their easy to use product:</p>

<blockquote class="social-embed" id="social-embed-859054476904337409" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><blockquote class="social-embed" id="social-embed-859043746339594241" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/gigastacey" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRlADAABXRUJQVlA4IEQDAADQDQCdASowADAAPp08l0mloyIhON24ALATiWYArDlBUx5jD4XwIsDpL8iXwdoH1jRZ8gRwK4CVA9zi3S0coa0ploY2areO6WE46I8rPKIM/OE2rdXgLXkGd0uru4/fMN6Y5mi/ZBstslpPD3gKpGdpYz813lefEADifa9F10+PnHfgtFZKYyIHvW0FmeFES+oJ4Qc8Q0LIKsMlbm/y/IpfU6AbPmHpY1zWMdGzqKw99FiSeKQW8hO0R8h4yxUzy9JfBMtpwhhJUc2Db6qWOyHlxMUIFhg1XXrfUYkd/qMYW+Ls/LJ/ABqzZG3J8mnHGL56dKYoeGPtvbJ4kM83uN8aiq1doFvAbTzxEtaaXWCyITBNdw53HGo26osDMNIqnXPJ5ZqjwoosWEdWfSzn9hS0OHVIiu7y8XI8aDwYqWiAWTY1A2zghoRMYgTpW0Hm4C1D+Jr+R5rDCOydAM1OmvUhXooApGan+kupwEnbbuYZwjR0WPpUZKyE2r520F30hDSASfnqmxMSadSKSk1EJ4SB59Vfc8zZMVQMAKllmjJIj+H/+wWjWxM5xGWUPLEncdigw5DiRxvj7OgAuLKoBo6o8555QAaSm5GE+CR7ekgiYh3Mpd+5crwPfrNf+FnsO9vyU80FBit3gonL202lXJNpRschNO1Y7FIc4ZGrBBg6VLfVQmLEZttxL2J40O/vdmys1jKljvyLMe+5lp+h2WRIRXNmM0DCwiK+p6rsCfguIhzky+mf+9hfdAdx6JIQzqwV2F61wecQk/8WwdM61XJKFQea+T7xfGsrtl08AZWlMiPMsC/EhQM46WxjxTkk1X9jyY2iqMvL+k3D7eUPjh61l6A1Rui/yAL0nT9zJafuLame0c5Y5VqkPm2k5sq50FD7UIruznMI7YtgwD6vYzumuo4iyJY4A4qlmzhzvGL/FvHafWgdm0U5gHQ9JdiH5MUV1HMkgqcdEekjpo6nN7O+uFxnSzsXPoH8tw6BLKiYGm2I8CzWQvqJH2nF4qkzRxzYsNjU4ovMkTLi4oK6evM9U9q7C6pt8sUEqYOnIa8PdFdxXA8WbsMUIz3F49BdQeQrfornplSWQ1c3NkHMpGldovAAAA==" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Stacey Higginbotham</p>@gigastacey</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody">This entire thread is killing me. Especially in light of Amazon's press about Alexa being easy as it's competitive differentiator. <a href="https://twitter.com/edent/status/858917427081613312">x.com/edent/status/8…</a><blockquote class="social-embed" id="social-embed-858917427081613312" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/edent" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody">Does anyone have an EASY tutorial for Alexa skills?<br>As in, not 27 steps where step 5 just says "install node" &amp; 26 says "see other tutorial"</section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/858917427081613312"><span aria-label="6 likes" class="social-embed-meta">❤️ 6</span><span aria-label="0 replies" class="social-embed-meta">💬 0</span><span aria-label="2 reposts" class="social-embed-meta">🔁 2</span><time datetime="2017-05-01T05:34:07.000Z" itemprop="datePublished">05:34 - Mon 01 May 2017</time></a></footer></blockquote></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/gigastacey/status/859043746339594241"><span aria-label="9 likes" class="social-embed-meta">❤️ 9</span><span aria-label="0 replies" class="social-embed-meta">💬 0</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2017-05-01T13:56:04.000Z" itemprop="datePublished">13:56 - Mon 01 May 2017</time></a></footer></blockquote><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/markcwebster" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRpwBAABXRUJQVlA4IJABAADQCACdASowADAAPrVSoUwnJKMiKrqpWOAWiWMAvYvpTpE0oxKFFbfOKbL7g8/p8A0yW2mmKyA1ySWdqZq6H6D4L8tRngldkqu8wfvRVVhAAP79KxzVbbMzJ5YOdRAOTJD/ybRvphypI2oAAitSpNYhSreqY0Fkevh7gTNlIppWZXAP2Vdtbh+QAnfhjps4Y4p0XSJ6pOJrapwoc6BTIk430bgVwMxI/o2qZ6RyEFcT+rdpITL5Ni7Uh8Eqkd0nibJXaP5FH5a2Hy54EMf6opv2ywVckCwpMt7vcuSh8cbPewgYT7AIDw5W96ebEznExkjw+tjxb/J7XEAdYkezuO7o/c0FNd+ec3X3m3cAyjXsFCfj+2nQn1XLHUspTMmzS+SKzFJynkT+VQpvVdIqmLn1WixZBwNv0jmMe7EY8surbPbWlkWOMzQPNRCNmnYIFSWKJcc39PQF7pjSJH7Yy9QXAxNibAsWbAYDBIq4HPH5Af8NCHvkNpFXtqxpTUA9bAGtXIdMzkYAm3xMi/QiMAAA" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Mark C. Webster</p>@markcwebster</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody"><small class="social-embed-reply"><a href="https://twitter.com/gigastacey/status/859043746339594241">Replying to @gigastacey</a></small><a href="https://twitter.com/gigastacey">@gigastacey</a> <a href="https://twitter.com/edent">@edent</a> this is what we're working on at <a href="https://twitter.com/sayspring">@sayspring</a>. We're just getting started, but take a look.</section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/markcwebster/status/859054476904337409"><span aria-label="0 likes" class="social-embed-meta">❤️ 0</span><span aria-label="1 replies" class="social-embed-meta">💬 1</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2017-05-01T14:38:42.000Z" itemprop="datePublished">14:38 - Mon 01 May 2017</time></a></footer></blockquote>

<p>Sadly, it's only available to US customers.</p>

<h2 id="driving-me-dotty"><a href="https://shkspr.mobi/blog/2017/05/amazon-alexa-and-solar-panels/#driving-me-dotty">Driving me dotty</a></h2>

<p>I reluctantly got a Dot because I thought it would be a nifty way to control <a href="https://shkspr.mobi/blog/2017/05/internet-connected-lightswitches-redux/">my new Internet connected light switches</a>.</p>

<p>Most Alexa skills require you to have the sort of lifestyle where you are regularly <em>desperate</em> to know what the weather is like at a specific airport. Or have a life which is intimately tied to the range of Amazon-only services.</p>

<p>Taking a look through what developers have released, it's an obvious conclusion that most developers have better things to do that spend time battling with Amazon's inadequate developer experience.</p>

<p>Oh, and there's the requisite "fart apps" and other high quality services;.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/05/Alexa-Fart-fs8.png" alt="You can ask your Alexa to Fart. Three different apps provide this service." width="1009" height="566" class="aligncenter size-full wp-image-25145">

<p>The future may be voice interfaces - but Amazon aren't leading the way there.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=25136&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2017/05/amazon-alexa-and-solar-panels/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		<enclosure url="https://shkspr.mobi/blog/wp-content/uploads/2017/05/VID_20170501_161804.webm" length="4644693" type="video/webm" />

			</item>
		<item>
		<title><![CDATA[Anatomy of an Amazon Phishing Attack]]></title>
		<link>https://shkspr.mobi/blog/2017/01/anatomy-of-an-amazon-phishing-attack/</link>
					<comments>https://shkspr.mobi/blog/2017/01/anatomy-of-an-amazon-phishing-attack/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 27 Jan 2017 10:05:05 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[bit.ly]]></category>
		<category><![CDATA[phishing]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=24734</guid>

					<description><![CDATA[Phishing is the devious practice of tricking users into giving away their usernames and passwords to fraudulent sites.  It is big business, and the best defence against it is constant vigilance.  I&#039;m going to walk you, step-by-step, through a scam that targetted me today.  Along the way we&#039;ll see how to avoid falling prey to these monsters.  It starts with a text  I was sent this SMS from a…]]></description>
										<content:encoded><![CDATA[<p>Phishing is the devious practice of tricking users into giving away their usernames and passwords to fraudulent sites.  It is big business, and the best defence against it is constant vigilance.</p>

<p>I'm going to walk you, step-by-step, through a scam that targetted me today.  Along the way we'll see how to avoid falling prey to these monsters.</p>

<h2 id="it-starts-with-a-text"><a href="https://shkspr.mobi/blog/2017/01/anatomy-of-an-amazon-phishing-attack/#it-starts-with-a-text">It starts with a text</a></h2>

<p>I was sent this SMS from a number that I didn't recognise.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/01/Fake-amazon-SMS-fs8.png" alt="Fake amazon SMS" width="475" height="231" class="aligncenter size-full wp-image-24736">

<p>Let's count the mistakes!</p>

<ol>
<li>In the UK, we place the currency symbol <em>before</em> the number.</li>
<li>British English spells "authorise" with an S rather than a Z.</li>
<li>Amazon don't send out links using the bitly shortening service.</li>
</ol>

<p>These phishers are hoping that you're too stupid to notice the mistakes.  They are also betting that you're too busy to think for a minute about whether Amazon are likely to contact you via SMS rather than email or app notification.</p>

<p>Let's say you're tired enough to click through, what do you find?</p>

<h2 id="stealing-beauty"><a href="https://shkspr.mobi/blog/2017/01/anatomy-of-an-amazon-phishing-attack/#stealing-beauty">Stealing Beauty</a></h2>

<p>At first glance, this looks <em>identical</em> to the regular Amazon mobile sign in page.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/01/Amazon-Scam-Site-fs8.png" alt="Amazon Scam Site" width="379" height="611" class="aligncenter size-full wp-image-24737">

<p>But! Look closely.  There are three obvious mistakes.</p>

<ol>
<li>No <code>https</code> - you should know by now that you <em>never</em> enter your password unless the website is protected with those magic letters.</li>
<li>The web address is <em>not</em> <code>amazon.co.uk</code>!  It is some other site.  Again, you should never enter a password unless you are sure that the site is legitimate.</li>
<li>Finally - what is that � character doing at the bottom of the site?  It should be a © symbol. Far too sloppy for Amazon.</li>
</ol>

<p>Surely you wouldn't fall for this?  Sadly, not everyone in the world is as bright as you.</p>

<h2 id="tell-me-more-tell-me-more"><a href="https://shkspr.mobi/blog/2017/01/anatomy-of-an-amazon-phishing-attack/#tell-me-more-tell-me-more">Tell me more, tell me more</a></h2>

<p>So, you unwisely entered your password.  The scammers are already riffling through your Amazon account with the stolen password. They're buying themselves toys using your credit card.  But they ain't done with you yet!</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/01/Amazon-Scam-Site-asking-for-your-info-fs8.png" alt="Amazon Scam Site asking for your info" width="379" height="611" class="aligncenter size-full wp-image-24738">

<p>They want <em>everything!</em>  Once they have your home address and phone number, they can bombard you with scams. Scroll down, and it gets worse.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/01/Amazon-Scam-Site-asking-for-even-more-info-fs8.png" alt="Amazon Scam Site asking for even more info" width="379" height="611" class="aligncenter size-full wp-image-24739">

<p>Your bank details! Your mother's maiden name! Are these details enough for them to fool your bank?  With all the information you're giving them, they'll be able to take over your entire life!</p>

<h2 id="fool-me-once"><a href="https://shkspr.mobi/blog/2017/01/anatomy-of-an-amazon-phishing-attack/#fool-me-once">Fool me once</a></h2>

<p>Because the scammers use <a href="https://shkspr.mobi/blog/?s=bitly">bitly</a>, we can take a look at how many people are clicking through this link.</p>

<p>By the time Bitly had flagged the link as malicious, over 250 people had clicked on it.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2017/01/Bitly-Amazon-Scam-fs8.png" alt="A graph showing how many people clicked the link" width="350" height="389" class="aligncenter size-full wp-image-24735">

<p>Would you have fallen for it? These scammers are betting that you're not paying attention. That you'll blindly trust any link you see.</p>

<p>Phone companies are powerless to stop this sort of spam - SIM cards can be purchased anonymously, and computers can pump out thousands of texts before their suspicious behaviour is noticed.</p>

<p>Bitly knows it is a vector for phishing attacks, but can't check every link before it goes live.</p>

<p>The only solid defence is <em>you!</em>  It is up to you to keep your wits up, to examine every message you receive, and every link you click.  You have to stay safe <em>all the time</em> - the scammers only need to get lucky once.</p>

<p>If you want to harden your defences, you need to take action now.</p>

<ol>
<li><a href="https://shkspr.mobi/blog/2016/12/some-thoughts-on-amazons-2fa/">Activate Two-Factor Authentication for Amazon</a> - even if someone steals your password, they'll also need your phone in order to log in.</li>
<li>Use <a href="https://www.lastpass.com/">LastPass</a> to generate strong and <em>unique</em> passwords for every site you use.  If you use the same password on multiple sites - it is only a matter of time before one is lost, and then all are lost.</li>
</ol>

<p>Stay safe out there!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=24734&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2017/01/anatomy-of-an-amazon-phishing-attack/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Some thoughts on Amazon's 2FA]]></title>
		<link>https://shkspr.mobi/blog/2016/12/some-thoughts-on-amazons-2fa/</link>
					<comments>https://shkspr.mobi/blog/2016/12/some-thoughts-on-amazons-2fa/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 29 Dec 2016 12:06:02 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[2fa]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[usability]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=24512</guid>

					<description><![CDATA[Amazon now let you secure your account with Two-Factor-Authentication (2FA). This means you can log on with a one-time password which changes every minute.  For some reason, Amazon call it Two-Step-Verification (2SV) - but it is exactly the same as all the other 2FA solutions.  The Process  There&#039;s no direct link to 2FA settings.  So the process is slightly convoluted.  Assuming you are signed in …]]></description>
										<content:encoded><![CDATA[<p>Amazon now let you secure your account with Two-Factor-Authentication (2FA). This means you can log on with a one-time password which changes every minute.  For some reason, Amazon call it Two-Step-Verification (2SV) - but it is exactly the same as all the other 2FA solutions.</p>

<h2 id="the-process"><a href="https://shkspr.mobi/blog/2016/12/some-thoughts-on-amazons-2fa/#the-process">The Process</a></h2>

<p>There's no <em>direct</em> link to 2FA settings.  So the process is slightly convoluted.  Assuming you are signed in to your Amazon account, you need to</p>

<ul>
<li>Go to <a href="https://www.amazon.co.uk/your-account">https://www.amazon.co.uk/your-account</a></li>
<li>Click on "Login &amp; Security Settings"</li>
<li>Then "Advanced Security Settings"</li>
</ul>

<p>You can now start to add 2FA to your account.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2016/12/amazon-2fa-fs8.png" alt="A screen from Amazon showing how to use 2FA" width="721" height="610" class="aligncenter size-full wp-image-24513">

<p>There are two ways you can get your 2FA code.  The most secure way is by using an authenticator app like <a href="https://www.authy.com/">Authy</a> or <a href="https://freeotp.github.io/">FreeOTP</a>.</p>

<p>If you can't install apps - or just don't like them - you can get your code delivered to you via SMS.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2016/12/Amazon-phone-format-fs8.png" alt="Amazon asking for your phone number, they use a weird format" width="490" height="316" class="aligncenter size-full wp-image-24514">

<p>Let's ignore the American number formatting (<a href="https://web.archive.org/web/20171222020924/https://www.youtube.com/watch?v=Tl1OAx9u1ok">555</a>!) - is an SMS code sensible?</p>

<ul>
<li>SMS works everywhere, even on the dumbest phone.</li>
<li>No app needed.</li>
<li>Swap your SIM to a new phone and have instant access.</li>
</ul>

<p>That last one is the biggest weakness. It is <em>terrifyingly</em> easy for a scammer to ring up your phone company and get your number swapped to a new SIM.  If a scammer wants the codes off your app they have to physically steal your phone and then unlock it (you do have a secure password, right?).  With SMS, all they have to do is convince some hapless call centre worker that you need your number transferred.</p>

<p>There's also the little matter that SMS isn't encrypted - but if the security services desperately want access to your Amazon account, I'm sure they have their own means.</p>

<h2 id="2fa-problems"><a href="https://shkspr.mobi/blog/2016/12/some-thoughts-on-amazons-2fa/#2fa-problems">2FA Problems</a></h2>

<p>Far from being a scrappy start-up, Amazon is now a maze of interconnected legacy systems.  There are several ancient services with Amazon can't or won't update.  This means they don't get 2FA support.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2016/12/Amazon-2fa-problems-fs8.png" alt="Some of Amazon's apps don't support 2FA" width="724" height="505" class="aligncenter size-full wp-image-24516">

<p>This is a <a href="https://shkspr.mobi/blog/2016/06/paypal-doesnt-care-about-security/">problem which I recently encountered with PayPal</a>.  Old apps don't support new security - weakening the usefulness of security for everyone.</p>

<p>Of course, there's no mention of <em>which</em> apps don't support 2FA.  Their proposed solution of sticking your 2FA code to the end of your password is... interesting.  It implies that if the system doesn't recognise your password decrypted password, it will split it in two and try it again. I wonder if that leaves them open to subtle timing attacks, or any other issues?</p>

<p>The point of 2FA is that you use it <em>everywhere</em> - otherwise you're introducing a weak point in your security. Amazon will happily let you turn off 2FA on specific devices.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2016/12/Amazon-2FA-skip-codes-fs8.png" alt="A screen letting you know that you can disable 2FA on specific devices." width="723" height="170" class="aligncenter size-full wp-image-24515">

<p>I can <em>kinda</em> see their reasoning. It is annoying to be forced into using the 2FA on your regular handset. But that's also the point. Making it slightly harder for us makes it <em>extraordinarily</em> hard for an attacker.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2016/12/Amazon-Phone-Login-fs8.png" alt="A mobile phone screen showing the Amazon login page, there is an option to disable 2FA" width="480" height="523" class="aligncenter size-full wp-image-24518">

<p>Despite these shortcomings, I urge you to switch on 2FA. Amazon holds a <a href="https://medium.com/@espringe/amazon-s-customer-service-backdoor-be375b3428c4#.lfbb3yppi">surprising amount of your personal data</a> - and <a href="https://www.wired.com/2012/08/apple-amazon-mat-honan-hacking/">the consequences of your Amazon account being hacked can be dire</a>.</p>

<p>There are <a href="https://twofactorauth.org/">hundreds of sites which support 2FA</a>. You should make sure you use it wherever possible.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=24512&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2016/12/some-thoughts-on-amazons-2fa/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Goodbye Amazon Prime]]></title>
		<link>https://shkspr.mobi/blog/2016/02/goodbye-amazon-prime/</link>
					<comments>https://shkspr.mobi/blog/2016/02/goodbye-amazon-prime/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 04 Feb 2016 14:35:37 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[amazonfail]]></category>
		<category><![CDATA[prime]]></category>
		<category><![CDATA[rant]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=22397</guid>

					<description><![CDATA[(To the tune of the popular Elton John song.)  I&#039;ve often joked that if my employers could pay me in Amazon vouchers, it would save me a lot of hassle.  I&#039;m one of those insufferable people who prefers a delivery driver dropping off a single light bulb rather than having to pop to the shops like some sort of savage.  But now the dream is over.  Amazon have bundled their sub-standard video…]]></description>
										<content:encoded><![CDATA[<p>(To the tune of the popular Elton John song.)</p>

<p>I've often joked that if my employers could pay me in Amazon vouchers, it would save me a lot of hassle.  I'm one of those insufferable people who prefers a delivery driver dropping off a single light bulb rather than having to pop to the shops like some sort of savage.</p>

<p>But now the dream is over.  Amazon have bundled their sub-standard video offering, a moribund music subscription, and an underwhelming photo backup service in with their excellent free delivery service.  In doing so, they've jacked the price from fifty to eighty quid.</p>

<p><a href="https://shkspr.mobi/blog/2015/02/get-cheaper-amazon-prime-without-instant-video/">Last year I was able to convince them to give me Prime delivery at the old price</a>.  But this year?  No dice.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2016/02/No-more-prime.png" alt="No more prime" width="720" height="630" class="aligncenter size-full wp-image-22402">

<p>And so now I get this passive-aggressive message whenever I visit Amazon.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2016/02/prime-no-renew-fs8.png" alt="prime no renew-fs8" width="1085" height="75" class="aligncenter size-full wp-image-22403">

<p>Here's the thing - I don't listen to much music, I don't live in an area with same day delivery, I already have a photo backup service, and I don't use a Kindle for my reading. Even if I wanted to watch more TV (I don't) Amazon refuse to build an app for my fairly recent smart TV.  The same TV I bought on Amazon...</p>

<p>This really shouldn't come as a surprise to me.  Amazon works on a socialist model - as described by the CEO Jeff Bezos:</p>

<blockquote><strong>Levy:</strong> Speaking of pricing, I wanted to ask about your decision to include streaming video as part of Amazon Prime. Why not charge separately for that? It’s a completely different service, isn’t it?<br><br>
<strong>Bezos:</strong> There are two ways to build a successful company. One is to work very, very hard to convince customers to pay high margins. The other is to work very, very hard to be able to afford to offer customers low margins. They both work. We’re firmly in the second camp. It’s difficult—you have to eliminate defects and be very efficient. But it’s also a point of view. We’d rather have a very large customer base and low margins than a smaller customer base and higher margins.
<br>
<cite><a href="https://www.wired.com/story/ceo-of-the-internet/">Jeff Bezos Owns the Web in More Ways Than You Think - Wired Magazine, 2011</a></cite>
</blockquote>

<p>The more people taking part, the cheaper the cost for everyone.  As a political philosophy I'm all for it, but I'm not keen on it being foisted on me as part of a capitalist transaction.</p>

<p>I personally benefit from a well educated, healthy public even if I don't use the services myself - I'm not sure I'll see any benefit from people being able to watch re-runs of Downton Abbey!</p>

<p>Eighty quid for "free" delivery is just too much.  I dare say I'll still shop there, but not with as much regularity.</p>

<p>Jeff, if you're reading, please just offer your delivery service as a separate subscription.</p>

<p>I know that Amazon won't mourn the loss of one customer.  But I mourn the fact that the subscription economy is slowly killing the services I enjoy.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=22397&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2016/02/goodbye-amazon-prime/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Get Cheaper Amazon Prime *Without* Instant Video!]]></title>
		<link>https://shkspr.mobi/blog/2015/02/get-cheaper-amazon-prime-without-instant-video/</link>
					<comments>https://shkspr.mobi/blog/2015/02/get-cheaper-amazon-prime-without-instant-video/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 01 Feb 2015 17:40:27 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[prime]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=20423</guid>

					<description><![CDATA[tl;dr If you have no need for Prime Video, you can ask Amazon for a discount. They&#039;ll knock £30 off the price - taking it down to £49.  I spoke to customer services - here&#039;s the transcript (edited for clarity) :    To be clear, Amazon weren&#039;t forthcoming in whether this was available to everyone.  I suggest you ask Amazon very nicely!  In my case, I haven&#039;t watched a single Amazon video. I don&#039;t e…]]></description>
										<content:encoded><![CDATA[<p><abbr title="Executive Summary">tl;dr</abbr> If you have no need for Prime Video, you can ask Amazon for a discount. They'll knock £30 off the price - taking it down to £49.</p>

<p>I spoke to customer services - here's the transcript (edited for clarity) :</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2015/02/Amazon-Prime-Video-Transcript-fs8.png" alt="Amazon Prime Video Transcript-fs8" width="480" height="861" class="aligncenter size-full wp-image-20506">

<p>To be clear, Amazon weren't forthcoming in whether this was available to everyone.  I suggest you ask Amazon <em>very</em> nicely!</p>

<p>In my case, I haven't watched a single Amazon video. I don't even think I've logged into the service.  Both <a href="https://shkspr.mobi/blog/2014/02/i-still-dont-want-to-be-part-of-your-fucking-ecosystem/">Amazon and Panasonic refuse to support my TV</a>.  Even if they did, the <a href="http://www.amazon.co.uk/Prime-TV/b/?_encoding=UTF8&amp;camp=1634&amp;creative=19450&amp;linkCode=ur2&amp;node=3356011031&amp;tag=shkspr-21&amp;linkId=6MLUG2WYPTEKXAYR">list of shows available</a> really isn't particularly to my tastes.</p>

<p>Ideally, I'd like to unbundle their <a href="http://www.amazon.co.uk/gp/help/customer/display.html/?ie=UTF8&amp;camp=1634&amp;creative=19450&amp;linkCode=ur2&amp;nodeId=201480950&amp;tag=shkspr-21&amp;linkId=SNVDCHXZK5ZKUKOF">useless photo service</a> (I host my own) and their <a href="https://web.archive.org/web/20200924234419/https://www.amazon.co.uk/gp/feature.html?ie=UTF8&amp;docId=1000659983">Kindle Lending Library</a> (I have an actual Library Card which has more benefits).</p>

<p>Still, I can't grumble. £50 Prime is a pretty good deal.  Isn't it?</p>

<h2 id="is-prime-worth-it"><a href="https://shkspr.mobi/blog/2015/02/get-cheaper-amazon-prime-without-instant-video/#is-prime-worth-it">Is Prime Worth It?</a></h2>

<p>I <em>loved</em> Amazon Prime.  The day we moved house, as we sat exhausted on the sofa surrounded by boxes, I pulled out my smartphone and went crazy. The next morning, <em>even more</em> boxes arrived.  Everything from cleaning products to doormats.  Over the next few months, that's just how it was.  If I saw that we needed something, a couple of clicks on the mobile website and - hey presto - a box would appear the very next day.</p>

<p>I didn't bother to compare prices with other sites - just click and wait.  Once (and this is truly tragic) I was feeling a bit peckish on a Saturday afternoon, come Sunday morning the Amazon man dropped off a kilogram bag of chilli puff-rice crackers.  Mmmmmm chilli crackers.</p>

<p>For fifty quid a year, it was absolutely perfect.  Next day delivery on just about everything - from a single lightbulb to a cross-trainer, from last minute birthday presents to cooking supplies. Click, wait, get.</p>

<p>Then they went and <strong><a href="https://shkspr.mobi/blog/2014/02/i-still-dont-want-to-be-part-of-your-fucking-ecosystem/">screwed it all up</a>.</strong></p>

<p>They put the price up to eighty-quid.  Their rationale was they were now bundling their crappy video service with it.  Fine, I guess, but not for me - as <a href="https://shkspr.mobi/blog/2014/02/i-still-dont-want-to-be-part-of-your-fucking-ecosystem/">I described in detail earlier on my blog</a>.  They refuse to support any of the devices I own and, even if they did, there's nothing on there I find of value.</p>

<p>Last year I wangled an extension to my existing price of £49.  This year I've done the same.</p>

<p>So, the conundrum. Is it worth paying £50 a year for "free" next day delivery?</p>

<p>The central lie of Amazon Prime is "<a href="http://www.amazon.co.uk/gp/help/customer/display.html/?ie=UTF8&amp;camp=1634&amp;creative=19450&amp;linkCode=ur2&amp;nodeId=201015970&amp;tag=shkspr-21&amp;linkId=G2EUNU5E4SDXU4QS">One-Day Delivery at no extra cost for eligible items.</a>"</p>

<p>A lie? I think so.  It makes it sound like Prime items aren't more expensive than their regular brethren.
<img src="https://shkspr.mobi/blog/wp-content/uploads/2015/01/Prime-Cheaper-fs8.png" alt="Prime Cheaper" width="603" height="198" class="aligncenter size-full wp-image-20424"></p>

<p>That £4.99 product can be had for £4.25 - a 15% discount - although delivery isn't next day.</p>

<p>On a <a href="http://www.amazon.co.uk/gp/product/B0001P0K7W/ref=as_li_tl?ie=UTF8&amp;camp=1634&amp;creative=19450&amp;creativeASIN=B0001P0K7W&amp;linkCode=as2&amp;tag=shkspr-21&amp;linkId=R6GV7B6I7PO2HDT6">small pack of rawl plugs</a>, you're paying £2 for Prime's next day delivery.</p>

<p>For more expensive items, like a <a href="http://www.amazon.co.uk/gp/product/B00OYTAQAM/ref=as_li_tl?ie=UTF8&amp;camp=1634&amp;creative=19450&amp;creativeASIN=B00OYTAQAM&amp;linkCode=as2&amp;tag=shkspr-21&amp;linkId=UYRHNCHWPC6K5IDJ">PS4</a>, there's generally not price difference.  But it really does add up for smaller items.  And that's kinda the joy of Prime - I can order a single rawlplug, if that's all I need, without having to faff around on the high street.</p>

<p>Given the extra cost of (some) Prime items - is it worth paying for the service?</p>

<p>It's time for some maths! YAY! MATHS! (NB, these numbers are <strong>very</strong> fuzzy.)</p>

<p>Let's start with the number of items I've purchased from Amazon in the last year.  The US site <a href="https://web.archive.org/web/20150207064533/https://www.amazon.com/gp/help/customer/display.html?nodeId=200131240">allows users to export a spreadsheet of their orders</a>.  The UK site doesn't offer such a facility. Thanks Amazon for truly demonstrating your commitment to the <em>World Wide</em> Web!</p>

<p>According to my account, I bought around 80 items using Prime in 2014. Crikey. I may be an addict....</p>

<p>Anyway...</p>

<p>The <em>extra</em> cost of Prime for each item was ~50p - £2.50 - although not every item charged extra for being available on Prime.</p>

<p>The cost of next day delivery for non-Prime items is between £2 and £10 (!).</p>

<p>If you regularly pay for next day delivery, it's probably cheaper to get Prime.</p>

<p>If you don't <em>need</em> next day delivery...?</p>

<p>Hmmm....</p>

<p>Very very very roughly - Prime costs me £90.  £50 for membership and £40 in extra charges for next day delivery.  Over all the items I buy, it's <em>probably</em> a good deal...  I'd pay more if I didn't have Prime...</p>

<p>Ultimately, what I'm paying for is <strong>knowing when delivery will take place.</strong>  I work from my home in Oxford, an office in Slough, and an office in London.  I don't like buying something, then waiting until I'm in the correct location to pick it up.  I like placing an order on Saturday and having it arrive on Sunday.  Saying that an order will take 1-3 days makes it hard to plan where I have to be in order to get my item.</p>

<p>I'm fundamentally lazy.  And I wonder - is that worth the extra cost?</p>

<h2 id="dear-amazon"><a href="https://shkspr.mobi/blog/2015/02/get-cheaper-amazon-prime-without-instant-video/#dear-amazon">Dear Amazon</a></h2>

<p>If you're reading this blog, here's my wishlist!</p>

<ul>
    <li>Unbundle Prime delivery and video. Sure, offer them together at a discount price if you like - but good products don't need to be forced onto customers.</li>
    <li>Let customers export their data - in CSV or similar format. Take a look at <a href="https://www.gov.uk/government/news/the-midata-vision-of-consumer-empowerment">midata</a>.</li>
    <li>How about making Prime prices the same as regular items? That'd be nice.</li>
    <li>If an item isn't available on Prime - perhaps refund (some of?) the delivery charges.</li>
    <li>Stop making it hard for customers to decide whether they want to give your their custom.  The couple of hours I've spent writing this blog post could have been spent browsing your website.</li>
</ul>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=20423&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2015/02/get-cheaper-amazon-prime-without-instant-video/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[The Curious Case of Amazon's IMDb Adverts]]></title>
		<link>https://shkspr.mobi/blog/2014/11/the-curious-case-of-amazons-imdb-adverts/</link>
					<comments>https://shkspr.mobi/blog/2014/11/the-curious-case-of-amazons-imdb-adverts/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 11 Nov 2014 12:23:45 +0000</pubDate>
				<category><![CDATA[badvertising]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[NaBloPoMo]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=19884</guid>

					<description><![CDATA[The Internet Movie Database is one of the most venerable sites on the Web.  It was founded by a British programmer in 1990 as a collection of Usenet posts (kids, ask your parents).  By 1993 it was on the nascent World Wide Web - and was hosted out of Cardiff University in Wales.  IMDb was one of the earliest success stories for the UK Internet industry when, in 1998, Amazon.com bought them. …]]></description>
										<content:encoded><![CDATA[<p>The Internet Movie Database is one of the most venerable sites on the Web.  It was founded by a <a href="https://en.wikipedia.org/wiki/Col_Needham">British programmer</a> in 1990 as a collection of Usenet posts (kids, ask your parents).  By 1993 it was on the nascent World Wide Web - and was hosted out of <a href="https://web.archive.org/web/20141110052254/https://www.cs.cf.ac.uk/movies/">Cardiff University in Wales</a>.</p>

<p>IMDb was one of the earliest success stories for the UK Internet industry when, in 1998, <a href="http://www.secinfo.com/dr643.7kp.c.htm">Amazon.com bought them</a>.</p>

<p>Given its proud heritiage, why don't Amazon care about the British users of its site?  If you visit the site on your phone, this is the advert you see.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2014/11/IMDB-website-with-Amazon-advert-fs8.png" alt="IMDB website with Amazon advert" width="282" height="481" class="aligncenter size-full wp-image-19886">

<p>Oh! Cool! The new Kindle tablet. Why, I just <em>gotta</em> get me one of those! Let's click the link...</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2014/11/Amazon-Kindle-American-Website-fs8.png" alt="Amazon Kindle American Website" width="282" height="481" class="aligncenter size-full wp-image-19885">

<p>Oh...</p>

<p>Yup, the advert is for the <em>American</em> tablet. The price is listed in US Dollars and, once I'm on the Amazon.com website, there's no obvious way to get to the .co.uk version.</p>

<p>This is <strong>madness!</strong>  The IMDb is consistently ranked in the <a href="https://web.archive.org/web/20150317111045/http://www.alexa.com/siteinfo/imdb.com">top 50 most visited sites worldwide</a>. Over 60% of its visitors are from outside the USA.  Why are Amazon ignoring all those customers?</p>

<p>Mobile advertising really isn't that hard. You find a way to match a user to a product. One of the simplest ways to do that is to determine the country the user is in. You show Indian adverts to people living in India, and Japanese adverts to people living in Japan.  That's not rocket science.</p>

<p>If, for some strange reason, you can only afford to design a single advert - your back end services should redirect the user to the website which is most appropriate.  Most of the French people clicking on your link are going to want a site which is written in their language and priced in their currency.</p>

<p>It's unlike Amazon to leave money on the table like this.  They have a vast international audience and yet they're simply ignoring their needs.</p>

<p>Why?</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=19884&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2014/11/the-curious-case-of-amazons-imdb-adverts/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[I Still Don't Want To Be Part of Your Fucking Ecosystem]]></title>
		<link>https://shkspr.mobi/blog/2014/02/i-still-dont-want-to-be-part-of-your-fucking-ecosystem/</link>
					<comments>https://shkspr.mobi/blog/2014/02/i-still-dont-want-to-be-part-of-your-fucking-ecosystem/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Wed, 26 Feb 2014 12:14:42 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[ecosystems]]></category>
		<category><![CDATA[panasonic]]></category>
		<category><![CDATA[technology]]></category>
		<guid isPermaLink="false">http://shkspr.mobi/blog/?p=10060</guid>

					<description><![CDATA[One of the most popular blog posts I have written is called &#34;I Don&#039;t Want To Be Part of Your Fucking Ecosystem&#34;.  In it, I rant against service providers trying to lock their customers into a monoculture.  Companies are always looking for the edge which will make them stand out - they think that restricting what their users can do is the answer.  It is not.  Openness and network effects are the…]]></description>
										<content:encoded><![CDATA[<p>One of the most popular blog posts I have written is called <a href="https://shkspr.mobi/blog/2012/11/i-dont-want-to-be-part-of-your-fucking-ecosystem/" title="I Don't Want To Be Part of Your Fucking Ecosystem">"I Don't Want To Be Part of Your Fucking Ecosystem"</a>.</p>

<p>In it, I rant against service providers trying to lock their customers into a monoculture.  Companies are always looking for the edge which will make them stand out - they think that restricting what their users can do is the answer.  It is <strong>not</strong>.</p>

<p>Openness and network effects are the biggest drivers of usage - an MP3 bought from Amazon works on an iPod bought from Apple, and an MP3 bought from iTunes works perfectly on a Kindle Fire bought from Amazon.  Customers and businesses both win when open standards are embraced and lock-in is eschewed.</p>

<p>I started my blog post by asking for something I thought to be quite reasonable, but some high-priests of Brand Synergy took to be treason:</p>

<blockquote>I want to watch Nokia movies on my Samsung hardware running Google's Android, and then back them up to DropBox.</blockquote>

<p>Today I've rubbed up against the annoying side of proprietary unreasonableness.  Amazon Instant Video.</p>

<p>For reasons best know to themselves, the geniuses at Amazon have decided to put up the cost of Prime membership by 60%.  As well as getting next day delivery on thousands of items, I can now also watch Amazon Instant Video - previously known as LoveFilm.</p>

<p>Deep joy.</p>

<p>This has <a href="https://web.archive.org/web/20160312033456/http://www.amazon.co.uk/gp/help/customer/forums/ref=cm_cd_t_rvt_np?ie=UTF8&amp;cdForum=Fx8DKXNI5KP8IK&amp;cdPage=1&amp;cdThread=TxBHN262DYW04G#CustomerDiscussionsNew">gone</a> <a href="https://web.archive.org/web/20160312032749/http://www.amazon.co.uk/gp/help/customer/forums/ref=help_forum_tft_tp?ie=UTF8&amp;cdForum=Fx8DKXNI5KP8IK&amp;cdThread=Tx1FK1U1BCM6IZM">down</a> <a href="https://web.archive.org/web/20160312033943/http://www.amazon.co.uk/gp/help/customer/forums/ref=help_forum_tft_tp?ie=UTF8&amp;cdForum=Fx8DKXNI5KP8IK&amp;cdThread=Tx1N5A3094X3MZI">like</a> a <a href="https://web.archive.org/web/20160312032831/http://www.amazon.co.uk/gp/help/customer/forums/ref=help_forum_tft_tp?ie=UTF8&amp;cdForum=Fx8DKXNI5KP8IK&amp;cdThread=Tx18Y70KB69JMFF">lead</a> <a href="https://web.archive.org/web/20160312032742/http://www.amazon.co.uk/gp/help/customer/forums/ref=help_forum_tft_tp?ie=UTF8&amp;cdForum=Fx8DKXNI5KP8IK&amp;cdThread=Tx2GD32P7PTCWIZ">balloon</a> among many erstwhile Prime customers.  Not everyone likes watching TV, or even has the broadband to support this.</p>

<p>But, hey, I thought I'd give it a go before deciding if it wasn't for me.</p>

<h2 id="panasonic"><a href="https://shkspr.mobi/blog/2014/02/i-still-dont-want-to-be-part-of-your-fucking-ecosystem/#panasonic">Panasonic</a></h2>

<p>I have a fairly new <a href="https://web.archive.org/web/20131216225152/http://www.amazon.co.uk/Panasonic-TX-L37E5B-Widescreen-Internet-Freeview/dp/B0079WKG5Q">Panasonic TX-L37E5B</a> (as sold on Amazon). Barely 18 months old.  It's a "Smart" TV - with access to BBC iPlayer and a host of other services.</p>

<p>But not LoveFilm.</p>

<iframe title="will viera connect eventuallly have lovefilm functionality?" width="620" height="349" src="https://www.youtube.com/embed/xC-cVZI7FBE?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""></iframe>

<p>For over a year Panasonic has been refusing to update their app store to include Amazon's LoveFilm.  Or 40D, ITV Player, Demand 5, etc.  I wonder if they've done a deal with Netflix to keep competing services off their TVs? Or if <a href="https://web.archive.org/web/20140209152704/http://developer.vieraconnect.com/">Panasonic's SDK</a> is so hideous that Amazon simply can't deliver a competent service using them?</p>

<p>This is what <a href="https://web.archive.org/web/20140221165813/http://panasonic.net/avc/viera/global/internet_apps/category/1/0">Panasonic's ecosystem</a> looks like.  How many names there do you recognise?</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2014/02/Panasonic-Ecosystem-fs8.png" alt="Panasonic Ecosystem-fs8" width="773" height="292" class="aligncenter size-full wp-image-10065">

<p>I repeatedly contacted Panasonic for a comment about this, but each time I received the same bland reply.</p>

<blockquote class="social-embed" id="social-embed-437888483026542592" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/PanaService_UK" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRhYBAABXRUJQVlA4IAoBAABQBgCdASowADAAPrVWpU4nJKOiI4oA4BaJaQAHUe4gNIF7y2KOhp68Yvxe11o1Jc2eQMfUBEPV/pQuSAD++50Q+yKZYmyYVwzXPHA6RNCIgBeiNrgn4SRhTY2jVxO9sXJR3vxTPv+6YJWg81eC//QihYd8ikfzoHdr2okdYuiPAmau6moFrdZl3FPYBFAUXtw+3ZD7lgApUCXDbjAJILQdx/eTzb9tU/++NoWEY7ndTzex4ucNCvCeXxceqn+ZXErK5TkQfBXRMFDC5NobJ/drBUxGgN8XKww9rkfHKA3cYUmc4k06faXU4L8QV27QP4qvFU6I3Pd5H2/dVpfiW8YRg/ztWNgodAAAAA==" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Panasonic Service UK</p>@PanaService_UK</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody"><small class="social-embed-reply"><a href="https://twitter.com/edent/status/437865975913127936">Replying to @edent</a></small><a href="https://twitter.com/edent">@edent</a> We are looking into the possibility of adding services but cannot make any guarantee as to whether it will be possible at the moment</section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/PanaService_UK/status/437888483026542592"><span aria-label="0 likes" class="social-embed-meta">❤️ 0</span><span aria-label="1 replies" class="social-embed-meta">💬 1</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2014-02-24T09:55:24.000Z" itemprop="datePublished">09:55 - Mon 24 February 2014</time></a></footer></blockquote>

<p>Panasonic, it seems, are <a href="https://web.archive.org/web/20170905014206/http://eng.faq.panasonic.com/app/answers/detail/a_id/13836/p/5/related/1">quite happy to ignore customer demand</a>.  Once they have your money, they cease to care.</p>

<p>I spoke to Amazon about this and asked which TVs they support:</p>

<blockquote><p> I have checked into this, and I can see that the eligible models for the televisions are:
</p><p>LG Smart TV (2012 or newer)
</p><p>Samsung Smart TV (2012 or newer)
</p><p>and Sony Smart TV (2010 or newer) </p></blockquote>

<p>Ah well, I thought, I can just use Panasonic's Web Browser to access LoveFilm, eh?</p>

<p></p><div id="attachment_10061" style="width: 730px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-10061" src="https://shkspr.mobi/blog/wp-content/uploads/2014/02/Panasonic-LoveFilm-Silverlight.jpg" alt="You need Silverlight software version 4.0 or higher to watch this title." width="720" height="540" class="size-full wp-image-10061"><p id="caption-attachment-10061" class="wp-caption-text">You need Silverlight software version 4.0 or higher to watch this title.</p></div><p></p>

<p>It looks like <a href="https://www.computerworld.com/article/1406672/netflix-to-dump-silverlight-microsoft-s-stalled-technology.html">rival Netflix are abandoning Silverlight</a>. Even Microsoft, the technology's creator, <a href="https://learn.microsoft.com/en-gb/lifecycle/products/?terms=silverlight">sees no future in the decrepit software</a> -  it's not much of a surprise to see that it's not available in TV browsers.  But, perhaps, the browser will work with Flash sites?</p>

<blockquote><p>The web browser does not support Adobe Flashplayer, and therefore, is unable to display catch-up services such as ITV player and 4oD.  <strong>There are no current plans to upgrade the browser's compatibility</strong>.
</p><p><cite><a href="https://web.archive.org/web/20170618180159/http://eng.faq.panasonic.com/app/answers/detail/a_id/13325">Panasonic's FAQ</a></cite></p></blockquote>

<p>Now, in fairness, Panasonic <em>just about</em> supports some HTML5 video.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2014/02/Panasonic-HTML5.jpg" alt="Panasonic HTML5" width="720" height="612" class="aligncenter size-full wp-image-10064">

<p>So it's <em>theoretically</em> possible that Amazon could decide to use open standards for its new video service, and Panasonic TV owners would be able to watch via their browsers rather than having a dedicated app.</p>

<h2 id="android"><a href="https://shkspr.mobi/blog/2014/02/i-still-dont-want-to-be-part-of-your-fucking-ecosystem/#android">Android</a></h2>

<p>There's no Android App for Amazon Instant Video either.  Just let that sink in for a moment.   Amazon produce the Android powered Kindle Fire - and yet can't be bothered to produce a video streaming app for the millions of Android devices out there.</p>

<p><a href="https://play.google.com/store/search?q=amazon%20instant%20video"><img src="https://shkspr.mobi/blog/wp-content/uploads/2014/02/Amazon-Instant-Video-Google-Android-fs8.png" alt="Screenshot of search results forAmazon Instant Video on Google Play - nothing found." width="720" height="275" class="aligncenter size-full wp-image-10074"></a></p>

<p>Madness!  Or, a pathetic attempt to get people to buy Amazon's Kindle Fire tablets - seemingly the <a href="https://web.archive.org/web/20140227041923/http://www.amazon.co.uk/gp/video/ontv/devices">only Android devices allowed to access their streaming service</a>.</p>

<h2 id="ecosystems-can-go-to-hell"><a href="https://shkspr.mobi/blog/2014/02/i-still-dont-want-to-be-part-of-your-fucking-ecosystem/#ecosystems-can-go-to-hell">"Ecosystems" Can Go To Hell</a></h2>

<p>Amazon - for reasons best known to them - have decided to bundle a physical-goods delivery system and a video-streaming platform.  I'm sure an MBA somewhere can explain why this multiplay service is destined to win hearts and minds.</p>

<p>Because Amazon have chosen to go down a locked and proprietary route, they've missed out on the interoperability which makes the world wonderful.</p>

<p>I'm not a Luddite.  I have a modern TV, smartphones, tablets, and games consoles - none of which Amazon have chosen to support.</p>

<p>Actually, my Xbox 360 <em>will</em> support it - after I pay <a href="http://www.amazon.co.uk/gp/product/B000B5KMSE/ref=as_li_ss_tl?ie=UTF8&amp;camp=1634&amp;creative=19450&amp;creativeASIN=B000B5KMSE&amp;linkCode=as2&amp;tag=shkspr-21">£40 per year for Xbox Live Gold Membership</a>.</p>

<p>Here's an idea... Amazon could use open standards, develop apps which work on the majority of available platforms, and gather millions of customers who <strong>actually want their service</strong>.</p>

<p>Instead, they've gone with the rent-seeking approach of strong-arming their customers into paying more for a service they cannot use and do not want.</p>

<p>I've no doubt some folk will cancel their Prime membership - but enough will put up with the price rise to make this quarter's numbers look just <em>swell!</em></p>

<p>Customers get screwed and Amazon gets to artificially inflate the numbers on its moribund streaming service.</p>

<p>This will not do.</p>

<p>I <strong>do not want</strong> services which only run on specially blessed devices.  <em>No one wants that!</em>  Companies which artificially restrict access in order to prop up their business models don't deserve to survive in the modern, interconnected world.</p>

<p>The true meaning of "ecosystem" is a bunch of independent organisms competing <em>and</em> co-operating. Symbiosis - not synergy.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=10060&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2014/02/i-still-dont-want-to-be-part-of-your-fucking-ecosystem/feed/</wfw:commentRss>
			<slash:comments>30</slash:comments>
		
		
			</item>
	</channel>
</rss>
