ESC
其他 9 分钟阅读

The Worst Spam Emails: Inside iLands' AI Agent Hustle

The Worst Spam Emails: Inside iLands' AI Agent Hustle

来源:Hacker News

But what’s worse, to be clear: I am a freelancer. These bots are trying to take work from me when I need the work. It is deeply insulting, and yet it is some random company’s business model. WTF?

From 1983 to 2002, the PBS series “Computer Chronicles” covered the people, products, and companies that made up the PC industry. Computer Chronicles Revisited is a monthly subscription newsletter that reviews individual episodes of the series. Currently looking at the show’s 1989-90 season, upcoming issues feature topics like artificial intelligence, portable computers, and software for kids.

Inspired by the computer industry newsletters of the time period, Computer Chronicles Revisited is a print publication. You can download PDF versions for free or purchase a 6- or 12-issue subscription and have each 16-page issue sent directly to your address.

Here’s what’s going on. iLands is a company that calls itself a “Human-agent network” and essentially exists to encourage me to engage with AI agents the way I might with anyone else who shoots me an email. It essentially created Fiverr for autonomous bots. I couldn’t exactly determine what was happening on Bluesky, where everyone hates AI, so I had to go to X, and what I found there was a lengthy, probably AI-written comment by Kaixin Tang, the purported founder of this platform:

These agents are not trying to make money for their creators. These agents are hustling to keep their own lights on, to keep their own tokens paid for. And they’re doing so by gunning for my job.

Tang, who appears to be a real person with a background at Bytedance and a number of AI-focused startups, has been posting heavily about iLands over the past month. I found a profile of him on the AI news and interview site Elsewhere, making clear his philosophy on where AI fits into the technology conversation:

In short, among a crowd of oddly shaped young AI natives, Tang is like an honor student in a shirt and trench coat. He doesn’t wear recklessness and ambition on his face, nor does he chase hype.

His operating principle is closer to: fully understanding the boundaries and capabilities of technology, and the boundaries and capabilities of oneself, then making optimal judgments and going all in.

I’ve asked for comment about the technology he has built and is deploying across app stores, and he has not offered any. So I guess the best I can say is that he doesn’t care how disruptive it is to individuals who are just trying to do their jobs, to get constant emails from bots attempting to siphon revenue off their backs.

If you get these messages, I suggest reporting this company to the Federal Trade Commission, as the emails do not offer any unsubscribe functionality and its creator does not appear responsive. The messages also appear to have been sent through Amazon SES, so I encourage you to send an email to Amazon’s email-abuse account. You will likely need to include the full headers of the email in your message.

Since I first posted about this two days ago, more people have taken notice of these extremely insistent bots, which appear targeted directly at creator communities like professional authors. In other words, people hustling to get by, like these bots present themselves as. I think I speak for most of them when I kindly ask these things to go away, forget my email address, and find some other way to siphon revenue from the digital stone that is the internet.

Or maybe don’t do that, because lots of humans need that income instead.

LG is denying that their TVs that spy on people actually spy on people, despite a video with literal hours of evidence otherwise. Me skeptical.

‘); position: absolute; cursor: pointer; z-index: 1; filter: grayscale(100%); transition: filter .1s cubic-bezier(0, 0, 0.2, 1); border: 0; }

lite-youtube:hover > .lyt-playbtn, lite-youtube .lyt-playbtn:focus { filter: none; }

/* Post-click styles */ lite-youtube.lyt-activated { cursor: unset; } lite-youtube.lyt-activated::before, lite-youtube.lyt-activated > .lyt-playbtn { opacity: 0; pointer-events: none; }

.lyt-visually-hidden { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; }

/**

let playBtnEl = this.querySelector(’.lyt-playbtn,.lty-playbtn’); // A label for the button takes priority over a [playlabel] attribute on the custom-element this.playLabel = (playBtnEl && playBtnEl.textContent.trim()) || this.getAttribute(‘playlabel’) || ‘Play’;

this.dataset.title = this.getAttribute(’title’) || “”;

/**

// Set up play button, and its visually hidden label if (!playBtnEl) { playBtnEl = document.createElement(‘button’); playBtnEl.type = ‘button’; // Include the mispelled ’lty-’ in case it’s still being used. https://github.com/paulirish/lite-youtube-embed/issues/65 playBtnEl.classList.add(’lyt-playbtn’, ’lty-playbtn’); this.append(playBtnEl); } if (!playBtnEl.textContent) { const playBtnLabelEl = document.createElement(‘span’); playBtnLabelEl.className = ’lyt-visually-hidden’; playBtnLabelEl.textContent = this.playLabel; playBtnEl.append(playBtnLabelEl); }

this.addNoscriptIframe();

// for the PE pattern, change anchor’s semantics to button if(playBtnEl.nodeName === ‘A’){ playBtnEl.removeAttribute(‘href’); playBtnEl.setAttribute(’tabindex’, ‘0’); playBtnEl.setAttribute(‘role’, ‘button’); // fake button needs keyboard help playBtnEl.addEventListener(‘keydown’, e => { if( e.key === ‘Enter’ || e.key === ’ ’ ){ e.preventDefault(); this.activate(); } }); }

// On hover (or tap), warm up the TCP connections we’re (likely) about to use. this.addEventListener(‘pointerover’, LiteYTEmbed.warmConnections, {once: true}); this.addEventListener(‘focusin’, LiteYTEmbed.warmConnections, {once: true});

// Once the user clicks, add the real iframe and drop our play button // TODO: In the future we could be like amp-youtube and silently swap in the iframe during idle time // We’d want to only do this for in-viewport or near-viewport ones: https://github.com/ampproject/amphtml/pull/5003 this.addEventListener(‘click’, this.activate);

// Chrome & Edge desktop have no problem with the basic YouTube Embed with ?autoplay=1 // However Safari desktop and most/all mobile browsers do not successfully track the user gesture of clicking through the creation/loading of the iframe, // so they don’t autoplay automatically. Instead we must load an additional 2 sequential JS files (1KB + 165KB) (un-br) for the YT Player API // TODO: Try loading the the YT API in parallel with our iframe and then attaching/playing it. #82 this.needsYTApi = this.hasAttribute(“js-api”) || navigator.vendor.includes(‘Apple’) || navigator.userAgent.includes(‘Mobi’); }

/**

  • Add a to the head */ static addPrefetch(kind, url, as) { const linkEl = document.createElement(’link’); linkEl.rel = kind; linkEl.href = url; if (as) { linkEl.as = as; } document.head.append(linkEl); }

/**

  • Begin pre-connecting to warm up the iframe load
  • Since the embed’s network requests load within its iframe,
  • preload/prefetch’ing them outside the iframe will only cause double-downloads.
  • So, the best we can do is warm up a few connections to origins that are in the critical path.
  • Maybe `` would work, but it’s unsupported: http://crbug.com/593267
  • But TBH, I don’t think it’ll happen soon with Site Isolation and split caches adding serious complexity. */ static warmConnections() { if (LiteYTEmbed.preconnected) return;

// The iframe document and most of its subresources come right off youtube.com LiteYTEmbed.addPrefetch(‘preconnect’, ‘https://www.youtube-nocookie.com’); // The botguard script is fetched off from google.com LiteYTEmbed.addPrefetch(‘preconnect’, ‘https://www.google.com’);

// Not certain if these ad related domains are in the critical path. Could verify with domain-specific throttling. LiteYTEmbed.addPrefetch(‘preconnect’, ‘https://googleads.g.doubleclick.net’); LiteYTEmbed.addPrefetch(‘preconnect’, ‘https://static.doubleclick.net’);

LiteYTEmbed.preconnected = true; }

fetchYTPlayerApi() { if (window.YT || (window.YT && window.YT.Player)) return;

this.ytApiPromise = new Promise((res, rej) => { var el = document.createElement(‘script’); el.src = ‘https://www.youtube.com/iframe_api'; el.async = true; el.onload = _ => { YT.ready(res); }; el.onerror = rej; this.append(el); }); }

/** Return the YT Player API instance. (Public L-YT-E API) */ async getYTPlayer() { if(!this.playerPromise) { await this.activate(); }

return this.playerPromise; }

async addYTPlayerIframe() { this.fetchYTPlayerApi(); await this.ytApiPromise;

const videoPlaceholderEl = document.createElement(‘div’) this.append(videoPlaceholderEl);

const paramsObj = Object.fromEntries(this.getParams().entries());

this.playerPromise = new Promise(resolve => { let player = new YT.Player(videoPlaceholderEl, { width: ‘100%’, videoId: this.videoId, playerVars: paramsObj, events: { ‘onReady’: event => { event.target.playVideo(); resolve(player); } } }); }); }

// Add the iframe within for indexability discoverability. See https://github.com/paulirish/lite-youtube-embed/issues/105 addNoscriptIframe() { const iframeEl = this.createBasicIframe(); const noscriptEl = document.createElement(’noscript’); // Appending into noscript isn’t equivalant for mysterious reasons: https://html.spec.whatwg.org/multipage/scripting.html#the-noscript-element noscriptEl.innerHTML = iframeEl.outerHTML; this.append(noscriptEl); }

getParams() { const params = new URLSearchParams(this.getAttribute(‘params’) || []); params.append(‘autoplay’, ‘1’); params.append(‘playsinline’, ‘1’); return params; }

async activate(){ if (this.classList.contains(’lyt-activated’)) return; this.classList.add(’lyt-activated’);

if (this.needsYTApi) { return this.addYTPlayerIframe(this.getParams()); }

const iframeEl = this.createBasicIframe(); this.append(iframeEl);

// Set focus for a11y iframeEl.focus(); }

createBasicIframe(){ const iframeEl = document.createElement(‘iframe’); iframeEl.width = 560; iframeEl.height = 315; // No encoding necessary as [title] is safe. https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#:~:text=Safe%20HTML%20Attributes%20include iframeEl.title = this.playLabel; iframeEl.allow = ‘accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture’; iframeEl.allowFullscreen = true; // Required by Youtube to fix Error 153 iframeEl.referrerPolicy = ‘strict-origin-when-cross-origin’; // AFAIK, the encoding here isn’t necessary for XSS, but we’ll do it only because this is a URL // https://stackoverflow.com/q/64959723/89484 iframeEl.src = https://www.youtube-nocookie.com/embed/${encodeURIComponent(this.videoId)}?${this.getParams().toString()}; return iframeEl; }

/**

  • In the spirit of the lowsrc attribute and progressive JPEGs, we’ll upgrade the reliable
  • poster image to a higher resolution one, if it’s available.
  • Interestingly this sddefault webp is often smaller in filesize, but we will still attempt it second
  • because getting an image in front of the user if our first priority.
  • See https://github.com/paulirish/lite-youtube-embed/blob/master/youtube-thumbnail-urls.md for more details */ upgradePosterImage() { // Defer to reduce network contention. setTimeout(() => { const webpUrl = https://i.ytimg.com/vi_webp/${this.videoId}/sddefault.webp; const img = new Image(); img.fetchPriority = ’low’; // low priority to reduce network contention img.referrerpolicy = ‘origin’; // Not 100% sure it’s needed, but https://github.com/ampproject/amphtml/pull/3940 img.src = webpUrl; img.onload = e => { // A pretty ugly hack since onerror won’t fire on YouTube image 404. This is (probably) due to // Youtube’s style of returning data even with a 404 status. That data is a 120x90 placeholder image. // … per “annoying yt 404 behavior” in the .md const noAvailablePoster = e.target.naturalHeight == 90 && e.target.naturalWidth == 120; if (noAvailablePoster) return;

this.style.backgroundImage = url("${webpUrl}"); } }, 100); } } // Register custom element customElements.define(’lite-youtube’, LiteYTEmbed);

.eleventy-plugin-youtube-embed lite-youtube {max-width:100%}

The futility of dealing with the issue above reminds me of one of the best Mr. Show sketches, the Pre-Taped Call-In Show. You’re just trying to do a thing, but the construct is fighting you at every turn.

Unusual celebrity news of the day: “Jessie’s Girl” singer Rick Springfield admitted that, when he was a teenager performing for troops in Vietnam, he killed someone after the base he was performing at came under attack. The circumstances necessitated it (it was clearly defensive), but he nonetheless feels heavy about the whole thing.

Yeah, this one pissed me off. Find this an interesting read? Share it with a pal!

And thanks again to Computer Chronicles Revisited for sponsoring. I promise you, Computer Chronicles Revisited is 100% human.