Pages

marți, 7 iulie 2026

News : Little Sheep Valley Announcement Trailer

News : Loft vs Sweep vs Patch in Plasticity.

News : Grok Voice Agent Builder Beta.

Voice Agent Builder is now live in beta: a no-code platform for production voice agents with Grok Voice. Every account includes a free phone number. Create a voice agent in under 2 minutes, then call it from your browser.
It’s for operators and developers who want high-volume production voice agents without building the stack from scratch. You get telephony, knowledge retrieval, tools, guardrails, and observability in one place. You can also keep what you already have: bring existing phone numbers, wire your APIs, or connect MCP servers.
Most voice stacks stitch together speech-to-text, a language model, and text-to-speech, often across different providers. Every hop adds latency and new failure modes. Voice Agent Builder is one interface built for Grok Voice, tightly coupled to the model.

Google Apps Script : example of transition from a Google Sheet to a formatted Google Doc.

This script that automates the transition from a Google Sheet to a formatted Google Doc. Here is a breakdown of what this solution does:
Custom Menu Integration: The script adds a Custom Menu directly into your Google Sheet interface. With a single click, you can trigger processes like fetching data or generating reports, making the tool incredibly easy to use without touching the code.
This example is based on this URL : https://www.planetpython.org/opml.xml.
Intelligent Data Processing: It doesn't just copy text; it parses RSS and Atom feeds, extracts titles and links, and prepares them for your document. It intelligently handles the HYPERLINK formulas you use in Sheets, translating them into real, clickable links in your final document.
Automatic Folder Management: One of the most useful features of this script is its ability to keep your Drive organized. Instead of cluttering your root directory, the script automatically identifies the folder where your source spreadsheet is located and creates the new document right there.
Built-in Troubleshooting: I have included logging functionality throughout the code. If a link is malformed or a feed fails to load, the script logs exactly what happened, allowing you to debug issues quickly via the Apps Script Dashboard.
Let's see the source code for Google Apps Scripts:
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('Custom Menu')
    .addItem('Read OPML PlanetPython', 'fetchAndProcessFeed')
    .addItem('Download Selected Content', 'downloadSelectedContentWrapper')
    .addItem('Send Sheet via Email', 'sendSheetViaEmail')
    .addToUi();
}

function fetchAndProcessFeed() {
  const dateTime = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyy-MM-dd_HH-mm");
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  let sheet = spreadsheet.getSheetByName(dateTime);
  
  if (!sheet) {
    sheet = spreadsheet.insertSheet(dateTime);
  } else {
    sheet.clear();
  }
  
  sheet.appendRow(["Date", "Source", "Title", "Select"]);
  
  const opmlUrl = "https://www.planetpython.org/opml.xml";
  const opmlContent = UrlFetchApp.fetch(opmlUrl).getContentText();
  const opmlDoc = XmlService.parse(opmlContent);
  const outlines = opmlDoc.getRootElement().getChild("body").getChildren("outline");
  
  outlines.forEach(outline => {
    const text = outline.getAttribute("text")?.getValue().replace(/"/g, '""').replace(/[<>&]/g, '') || "";
    const xmlUrl = outline.getAttribute("xmlUrl")?.getValue() || "";
    
    try {
      const feedContent = UrlFetchApp.fetch(xmlUrl).getContentText();
      const feedDoc = XmlService.parse(feedContent);
      const root = feedDoc.getRootElement();
      
      if (root.getName() === "rss") {
        processRssFeed(root, text, xmlUrl, sheet);
      } else if (root.getName() === "feed") {
        processAtomFeed(root, text, xmlUrl, sheet);
      }
    } catch (e) {
      Logger.log(`Error processing feed ${text} (${xmlUrl}): ${e}`);
    }
  });
}

function processRssFeed(root, source, xmlUrl, sheet) {
  const items = root.getChild("channel")?.getChildren("item") || [];
  items.forEach(item => {
    const title = item.getChild("title")?.getValue().replace(/"/g, '""').replace(/[<>&]/g, '') || "";
    const pubDate = item.getChild("pubDate")?.getValue() || "";
    const link = item.getChild("link")?.getValue().replace(/[<>&]/g, '') || xmlUrl;
    sheet.appendRow([
      pubDate,
      `=HYPERLINK("${xmlUrl}", "${source}")`,
      `=HYPERLINK("${link}", "${title}")`,
      ""
    ]);
  });
}

function processAtomFeed(root, source, xmlUrl, sheet) {
  const entries = root.getChildren("entry") || [];
  entries.forEach(entry => {
    const title = entry.getChild("title")?.getValue().replace(/"/g, '""').replace(/[<>&]/g, '') || "";
    const updated = entry.getChild("updated")?.getValue() || "";
    const link = entry.getChild("link")?.getAttribute("href")?.getValue().replace(/[<>&]/g, '') || xmlUrl;
    sheet.appendRow([
      updated,
      `=HYPERLINK("${xmlUrl}", "${source}")`,
      `=HYPERLINK("${link}", "${title}")`,
      ""
    ]);
  });
}

function downloadSelectedContentWrapper() {
  downloadSelectedContent();
}

async function downloadSelectedContent() {
  const dateTime = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "yyyy-MM-dd_HH-mm");
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = spreadsheet.getActiveSheet();
  const data = sheet.getDataRange().getValues();
  const doc = DocumentApp.create(`Content_${dateTime}`);
  const folderId = DriveApp.getFileById(spreadsheet.getId()).getParents().next().getId();
  DriveApp.getFileById(doc.getId()).moveTo(DriveApp.getFolderById(folderId));
  
  let contentAdded = false;
  const body = doc.getBody();
  
  for (let i = 1; i < data.length; i++) {
    const row = data[i];
    if (row[3] == 1) {
      const sourceMatch = row[1].toString().match(/^=HYPERLINK\("([^"]+)",\s*"([^"]+)"\)$/);
      const source = sourceMatch ? sourceMatch[2] : row[1].toString().replace(/[<>&]/g, '') || "Unknown source";
      const titleMatch = row[2].toString().match(/^=HYPERLINK\("([^"]+)",\s*"([^"]+)"\)$/);
      const title = titleMatch ? titleMatch[2] : row[2].toString().replace(/[<>&]/g, '');
      const link = titleMatch ? titleMatch[1] : "";
      
      Logger.log(`Processing ${title} with link: ${link}`);
      
      try {
        body.appendParagraph(source).setHeading(DocumentApp.ParagraphHeading.HEADING1);
        const titleParagraph = body.appendParagraph(title).setHeading(DocumentApp.ParagraphHeading.HEADING2);
        if (link) titleParagraph.setLinkUrl(link); // Titlu ca hyperlink
        body.appendParagraph(""); // Spațiu între intrări
        contentAdded = true;
        Logger.log(`Added ${title} with link`);
      } catch (e) {
        Logger.log(`Error processing ${title} (${link}): ${e}`);
        body.appendParagraph(source).setHeading(DocumentApp.ParagraphHeading.HEADING1);
        const titleParagraph = body.appendParagraph(title).setHeading(DocumentApp.ParagraphHeading.HEADING2);
        if (link) titleParagraph.setLinkUrl(link);
        body.appendParagraph("");
        contentAdded = true;
      }
    }
  }
  
  if (!contentAdded) {
    Logger.log("No content was added to the document.");
    body.appendParagraph("No content was selected or available.");
  }
}


function sendSheetViaEmail() {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = spreadsheet.getActiveSheet();
  const sheetName = sheet.getName();
  const data = sheet.getDataRange().getValues();
  
  let htmlContent = `
    <html>
      <head>
        <title>${sheetName}</title>
      </head>
      <body>
        <h1>${sheetName}</h1>
        <table border="1">
          <tr>
            <th>Date</th>
            <th>Source</th>
            <th>Title</th>
            <th>Select</th>
          </tr>
  `;
  
  data.forEach((row, index) => {
    if (index > 0) {
      const date = row[0] || "";
      const sourceMatch = row[1].toString().match(/^=HYPERLINK\("([^"]+)",\s*"([^"]+)"\)$/);
      const sourceUrl = sourceMatch ? sourceMatch[1] : "";
      const sourceText = sourceMatch ? sourceMatch[2] : row[1].toString().replace(/[<>&]/g, '');
      const titleMatch = row[2].toString().match(/^=HYPERLINK\("([^"]+)",\s*"([^"]+)"\)$/);
      const titleUrl = titleMatch ? titleMatch[1] : "";
      const titleText = titleMatch ? titleMatch[2] : row[2].toString().replace(/[<>&]/g, '');
      const select = row[3] || "";
      htmlContent += `
        <tr>
          <td>${date}</td>
          <td><a href="${sourceUrl}">${sourceText}</a></td>
          <td><a href="${titleUrl}">${titleText}</a></td>
          <td>${select}</td>
        </tr>
      `;
    }
  });
  
  htmlContent += `
        </table>
      </body>
    </html>
  `;
  
  const mimetype = "application/epub+zip";
  const containerXml = `
    <?xml version="1.0"?>
    <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
      <rootfiles>
        <rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/>
      </rootfiles>
    </container>
  `;
  
  const contentOpf = `
    <?xml version="1.0" encoding="UTF-8"?>
    <package xmlns="http://www.idpf.org/2007/opf" unique-identifier="bookid" version="2.0">
      <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
        <dc:title>${sheetName}</dc:title>
        <dc:identifier id="bookid">urn:uuid:${Utilities.getUuid()}</dc:identifier>
        <dc:language>en</dc:language>
      </metadata>
      <manifest>
        <item id="content" href="content.html" media-type="application/xhtml+xml"/>
      </manifest>
      <spine>
        <itemref idref="content"/>
      </spine>
    </package>
  `;
  
  const blobs = [
    Utilities.newBlob("mimetype", "text/plain", "mimetype").setContentType(mimetype),
    Utilities.newBlob(containerXml, "application/xml", "META-INF/container.xml"),
    Utilities.newBlob(contentOpf, "application/xml", "OEBPS/content.opf"),
    Utilities.newBlob(htmlContent, "application/xhtml+xml", "OEBPS/content.html")
  ];
  
  const zipOutput = Utilities.zip(blobs, `Sheet_${sheetName}.epub`);
  
  MailApp.sendEmail({
    to: "catalinfest@gmail.com,catafest@yahoo.com",
    subject: `Sheet activ: ${sheetName}`,
    body: "Vezi atașat sheet-ul activ în format EPUB.",
    attachments: [zipOutput]
  });
}

luni, 6 iulie 2026

Tools : Visual Code Ollama extension for developers.

Use Ollama models in VS Code Chat.
The Ollama extension adds models from your running Ollama server to the VS Code model picker.
Ollama 0.17.6 or newer is recommended for cloud model sign-in and richer model metadata. Older Ollama versions may still work for local models.
Requirements
  • Visual Studio Code 1.120 or newer
  • Ollama installed and running
  • At least one local or cloud model available in Ollama

News : The First Descendant | Season 4 Episode 1 Story Trailer

duminică, 5 iulie 2026

News : Google - View Space Locations by NASA.

I found a map with all view space locations on google by nasauofl@gmail.com.

News : Security - OpenCVE teams can use automations.

We’re excited to introduce a major evolution in how OpenCVE helps teams manage CVEs: Automations.
If you use OpenCVE today, you already know the value of tracking CVEs that match your vendors and products. But as subscriptions grow, so does the noise. Every update, every score change, every new reference can demand attention.
Automations give you control over when, why, and how OpenCVE reacts to the CVEs in your projects.
Vulnerability monitoring is not just about detection. Security, SOC, DevSecOps, and engineering teams need to prioritize, triage, and act without drowning in alerts.
Until now, much of that logic lived inside notification configurations: event filters, CVSS thresholds, delivery rules, all bundled together. That worked, but it was hard to extend. You could notify, but you couldn’t easily assign a CVE, change its status, or build a scheduled digest with the same flexibility.