Welcome to Sky Blues Talk!

You're currently viewing the forum as a guest. Join thousands of fellow Coventry City fans today!

I made a thing that might help today

shmmeee

Statue Outside the CBS
Joined
Jul 11, 2011
Messages
77,322
Reaction score
83,151
Got ChatGPT to code me a widget for my phone that shows the top five thread titles on the CCFC forum. So in theory I don’t have to come here and get sucked in and can just watch for a thread about a new signing. It works as a piece of software it does not work as a way to stop my coming on SBT too much. Thought I’d share.

iOS you need to download an app called Scriptable then create a new script, past the below in, save it with a name, and then add the scriptable widget to your Home Screen and choose run script and select the one you made.

Here’s what it looks like:
IMG_4855.webp

Here’s the script:




Code:
// SkyBlueTalk — CCFC Top Threads (polished)
// Medium/Small widget. Auto dark/light, club sky-blue gradient.
// Taps: header → forum, each row → thread.

// ── CONFIG ─────────────────────────────────────────────────────────────────────
const FEED_URL = "https://www.skybluestalk.co.uk/forums/coventry-city-general-chat.7/index.rss";
const MAX_ITEMS = 5;             // keep 3–6 for Medium, 2–4 for Small
const TITLE_LINE_LIMIT = 1;      // 1 = tidy, 2 = roomier
const SHOW_REL_TIME = true;      // show “· 1h” after title
const TRIM_PREFIXES = [
  /^match\s*thread[:\-\s]*/i,
  /^pre[-\s]?match[:\-\s]*/i,
  /^post[-\s]?match[:\-\s]*/i,
  /^transfer(s)?[:\-\s]*/i,
  /^\[\s*rumou?r\s*\]\s*/i
];
// Colors
const SKY = Color.dynamic(new Color("#69b9ff"), new Color("#2b86d1"));
const DEEP = Color.dynamic(new Color("#1a6db3"), new Color("#154e80"));
const TEXT = Color.dynamic(Color.black(), Color.white());
const SUBTLE = Color.dynamic(new Color("#334155"), new Color("#b0c4d9"));
// ───────────────────────────────────────────────────────────────────────────────

async function fetchRSS(url){
  const req = new Request(url);
  req.headers = { "User-Agent": "ScriptableWidget/1.1 (+iOS)" };
  return await req.loadString();
}

function parseRSS(xml){
  const items = [];
  const blocks = xml.match(/<item>[\s\S]*?<\/item>/g) || [];
  for (let i=0; i<Math.min(blocks.length, MAX_ITEMS); i++){
    const b = blocks[i];
    const t = textOf(b, "title");
    items.push({
      title: prettifyTitle(t),
      link: textOf(b, "link"),
      date: new Date(textOf(b, "pubDate") || Date.now())
    });
  }
  return items;
}

function textOf(block, tag){
  const m = new RegExp(`<${tag}>([\\s\\S]*?)<\\/${tag}>`, "i").exec(block);
  return (m ? m[1] : "").replace(/<!\[CDATA\[|\]\]>/g,"").trim();
}

function prettifyTitle(t){
  let s = t.replace(/\s+/g," ").trim();
  for (const rx of TRIM_PREFIXES) s = s.replace(rx,"");
  // collapse bracketed prefixes like [Tickets], (H), etc. at start
  s = s.replace(/^(\[.*?\]|\(.*?\))\s+/g,"");
  return s;
}

function timeAgo(d){
  const secs = Math.max(1, (Date.now() - d.getTime())/1000);
  if (secs < 60) return `${Math.floor(secs)}s`;
  const mins = secs/60;
  if (mins < 60) return `${Math.floor(mins)}m`;
  const hrs = mins/60;
  if (hrs < 24) return `${Math.floor(hrs)}h`;
  const days = hrs/24;
  return `${Math.floor(days)}d`;
}

function header(w){
  const h = w.addStack();
  h.layoutHorizontally();
  h.centerAlignContent();
  h.url = "https://www.skybluestalk.co.uk/forums/coventry-city-general-chat.7/";
  const badge = SFSymbol.named("soccerball");
  const img = h.addImage(badge.image);
  img.imageSize = new Size(14,14);
  img.tintColor = TEXT;
  h.addSpacer(6);
  const t = h.addText("SkyBlueTalk — CCFC");
  t.font = Font.boldSystemFont(12);
  t.textColor = TEXT;
  h.addSpacer();
  const refresh = h.addText(new Date().toLocaleTimeString([], {hour:"2-digit", minute:"2-digit"}));
  refresh.font = Font.systemFont(10);
  refresh.textColor = SUBTLE;
}

function row(w, item){
  const s = w.addStack();
  s.layoutHorizontally();
  s.url = item.link;

  // bullet
  const dot = s.addText("•");
  dot.font = Font.boldSystemFont(13);
  dot.textColor = TEXT;
  s.addSpacer(6);

  // title
  const t = s.addText(item.title);
  t.font = Font.systemFont(13);
  t.textColor = TEXT;
  t.lineLimit = TITLE_LINE_LIMIT;

  if (SHOW_REL_TIME){
    s.addSpacer(6);
    const ago = s.addText(`· ${timeAgo(item.date)}`);
    ago.font = Font.systemFont(11);
    ago.textColor = SUBTLE;
  }
}

function makeWidget(items){
  const w = new ListWidget();
  const grad = new LinearGradient();
  grad.colors = [SKY, DEEP];
  grad.locations = [0, 1];
  grad.startPoint = new Point(0, 0);
  grad.endPoint = new Point(1, 1);
  w.backgroundGradient = grad;
  w.setPadding(10, 12, 10, 12);

  header(w);
  w.addSpacer(6);
  items.forEach((it, idx) => {
    row(w, it);
    if (idx < items.length-1) w.addSpacer(4);
  });

  return w;
}

async function run(){
  try{
    const xml = await fetchRSS(FEED_URL);
    const items = parseRSS(xml);
    const widget = makeWidget(items);
    if (config.runsInWidget) Script.setWidget(widget);
    else await widget.presentMedium();
  } catch (e){
    const w = new ListWidget();
    w.addText("SkyBlueTalk — error").font = Font.boldSystemFont(12);
    w.addText(String(e)).font = Font.systemFont(10);
    Script.setWidget(w);
  }
  Script.complete();
}
await run();
 
Ytho GIF
 
When I read the title I thought it was a commitment from you to not make any more idiotic posts
 
We can all get the benefit of your forensic insight on Brau now
 
ChatGPT actually managed that without so much debugging you basically had to write it yourself?
 
Can you not just use an RSS reader app? It saves trying to scrape and you get the clean xml

Ah maybe I can. Will have a look. The troubles with vibe coding.
 
ChatGPT actually managed that without so much debugging you basically had to write it yourself?

One shot ten seconds work. But as Nick points out not the best solution. So still very ChatGPT.
 
Should be able to get the RSS link for a certain forum 😁

If it works though, it works 🤣

I didn’t even realise SBT had an rss feed. I didn’t even realise rss feeds were still a thing.
 
Quite liked the intent here and set up the RSS feed for notifications, just for some absolute whopper to post that we’d signed Hughes
 

Users who are viewing this thread

Back
Top Bottom