first_page

studio status report: 2025-04

month 04 of 2025 was about envisioning a road map toward getting the next-generation b-roll player services working

Currently, the Studio canvas shows two warnings directly related to player services:

Obsidian Studio canvas detail

What should emerge from the visual detail above are:

  • Songhay Player (C♯) [not in a public repo]
  • Songhay Functions [will be a project inside the Songhay Player (C♯) Solution]

The Studio graph shows a whopping ten days were spent on Songhay Player (C♯) alone:

Songhay Player (C♯) in Obsidian graph

Stuff from the #day-job soaked up the bulk of the rest of my time where I learned something new yet again: how to generate SQL statements through ‘conversation’ (talking to myself) with a Jupyter Notebook. This is not quite as ginger-billionaire sexy (and security-hole-making) as using AI for the same purpose but this organic solo performance is far more energy efficient 😐

Whatever is written in the previous paragraph has nothing to do with the top priority of my Studio: generating a new index.html page with eleventy (see “sketching out development projects” below). My selected notes below should show that some time was spent on this ‘top priority’:

[[Songhay Publications Analytics|kintespace.com analytics]]: “Abusive AI Web Crawlers: Get Off My Lawn”

Is this abuse happening to kintespace.com?

This new attack comes from a great many IP addresses, each making a tiny number of requests – often just one – from viable-looking but randomly generated User-Agents. We’ve had some success detecting and blocking these but this has not been without some problems. There have been periods where some of our servers have been struggling under the sheer number of connections they’ve had to deal with and some of the blocks we’ve put in place have impacted some legitimate users, especially those on very old computers. If this is you then we’re sorry you’ve been caught up in this.

To give you some idea of the scale, one of our shared hosting servers has in the last month been averaging over 1.5 million fraudulent requests from 290,000 unique IP addresses per day. These are addresses that we have a very high confidence are not making legitimate requests. We’ve identified 5.1 million unique IP addresses during this period and 3.4 million of those have only made a single request, which has made it very difficult for us to block them proactively.

The vast majority of these requests are from consumer ISP networks from a wide variety of countries with Brazil being the biggest contributor by far.

—“Abusive AI Web Crawlers: Get Off My Lawn

[[Songhay Publications Analytics]]: adding "/rasxlog/entry/"

The addition of "/rasxlog/entry/" as a ‘content resource’ will drastically increase TotalFileHits:

SetTotalFileHits screenshot

The visualization shows the increase, drastically:

kinté hits screenshot

[[dotnet|.NET]]: not-very-effective JsonNode extension methods

These two extension methods are going in the wrong direction:

/// <summary>
/// Gets the reference-type property value of the specified <see cref="JsonNode"/>
/// of <see cref="JsonValueKind.Object" />
/// or defaults to null.
/// </summary>
/// <typeparam name="T">type constrained to <c>class</c></typeparam>
/// <param name="node">The <see cref="JsonNode"/>.</param>
/// <param name="propertyName">Name of the property.</param>
public static T? GetPropertyReferenceValueOrNull<T>(this JsonNode? node, string propertyName) where T: class
{
    JsonValue? jsonValue = node.GetPropertyJsonValueOrNull(propertyName);
    if (jsonValue == null) return null;

    return !jsonValue.TryGetValue(out T? value) ? null : value;
}

/// <summary>
/// Gets the property value of the specified <see cref="JsonNode"/>
/// of <see cref="JsonValueKind.Object" />
/// or defaults to null.
/// </summary>
/// <typeparam name="T">type constrained to <c>struct</c></typeparam>
/// <param name="node">The <see cref="JsonNode"/>.</param>
/// <param name="propertyName">Name of the property.</param>
public static T? GetPropertyValueOrNull<T>(this JsonNode? node, string propertyName) where T: struct
{
    JsonValue? jsonValue = node.GetPropertyJsonValueOrNull(propertyName);
    if (jsonValue == null) return null;

    return !jsonValue.TryGetValue(out T? value) ? null : value;
}

[!important] Constraining T to a struct should be replaced by an extension method that returns JsonValue.

Constraining T to a class should be replaced by an extension methods that return JsonArray and JsonObject.

Not doing this can lead to ‘losing the reference’ or perhaps cloning child nodes inside a JsonNode. For example, below jsonArray will lose its reference to the JsonArray inside node:

JsonNode? node = JsonNode.Parse(jO.RootElement.GetRawText());

JsonArray? jsonArray = node.GetPropertyReferenceValueOrNull<JsonArray>(summaryArrayPropertyName);

jsonArray?.Add(jOData);

[!error] Adding jOData to jsonArray will not update the JsonArray inside of node.

I have replaced GetPropertyReferenceValueOrNull<JsonArray> with:

public static JsonArray? GetPropertyJsonArrayOrNull(this JsonNode? node, string propertyName)  
{  
    if (node == null) return null;  
    if (node.GetJsonValueKind() != JsonValueKind.Object) return null;  
  
    if (!node.AsObject().TryGetPropertyValue(propertyName, out JsonNode? outputNode)) return null;  
  
    return outputNode is not JsonArray ? null : outputNode.AsArray();  
}

[[Azure]]: use IBM-speak; use the term “workload”

A workload, in the most general sense, is the amount of time and computing resources a system or network takes to complete a task or generate a particular output. It refers to the total system demand of all users and processes at a given moment.

—“What is a workload?

[[dotnet|.NET]]: IConfiguration and ILogger should never be null 💡✨

Previously, I thought that IConfiguration alone should never intentionally be null without regard to unit-testing scenarios. Now, I can include ILogger in this confidence because of my discovery of NullLogger.Instance [📖 docs ] #to-do

The good news is that the Microsoft.Extensions.Logging.Abstractions namespace comes with null objects right out of the box. All you need to do is use NullLogger.Instance and NullLoggerFactory.Instance as default instances in your constructor. That’s it. Your class can now depend on these instances, as though there is a real instance.

—“ILogger and Null Object Pattern

[[Songhay Publications - KinteSpace|kintespace.com]] is using “next generation” CSS 😐🧠🐈

The [[2025-03-29#cards as responsive, two-column grids|cards as responsive, two-column grids]] experiment is progressing quite well:

CodePen screenshot https://codepen.io/rasx/pen/raNbNwx

Certainly, I did not plan to run into the use of the @container at-rule [📖 docs ] instead of media queries. In the 2022 article, “Next Gen CSS: @container,” @container was considered a Chrome experiment:

Chrome is experimenting with @container, a property within the CSS Working Group Containment Level 3 spec being championed by Miriam Suzanne of Oddbird, and a group of engineers across the web platform. @container brings us the ability to style elements based on the size of their parent container.

BTW: placekitten.com has new competition: https://placecats.com/

[[dotnet|.NET]]: “.NET 10 Preview 3 is now available!”

[[dotnet|.NET 10]] picks:

[[Songhay Player]]: can etag data from [[Google]] be used to determine whether data has been changed? #to-do

I think the short answer is yes.

diff screenshot

The HTTP ETag is used for cache validation:

An ETag is an opaque identifier assigned by a Web server to a specific version of a resource found at a URL. If the resource representation at that URL ever changes, a new and different ETag is assigned. Used in this manner, ETags are similar to fingerprints and can quickly be compared to determine whether two representations of a resource are the same.

[!important] Recognizing ETags should speed up the processing of b-roll player data from [[Google]] dramatically 🧠💡

[[xUnit.net]]: my new ProjectDirectoryAttribute

Yesterday, while working on [[Songhay Player (C♯)]], I discovered that requiring a type argument for ProjectFileDataAttribute is unnecessary. My new Theory attribute, ProjectDirectoryAttribute takes advantage of what has always been there—the MethodInfo of the test method on the test class:

public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
    Type methodType = testMethod.DeclaringType.ToReferenceTypeValueOrThrow();

    //…

}

The intent behind ProjectDirectoryAttribute is to conveniently get the conventional directory of the *.csproj file on the test-method level. This attribute is just an [[xUnit.net]] wrapper around my GetNetCoreProjectDirectoryInfo method [🔗 GitHub ]. Although investigating whether some kind of “fixture” can be developed to share the project directory DirectoryInfo on the test class level is worth the effort #to-do, the ProjectDirectoryOption enumeration allows flexibility, changing the ‘test root’ path for each method.

ProjectDirectoryAttribute needs to be migrated into the [[Songhay Core (C♯)]] Solution #to-do Also, the overloads containing the Type argument of the ProjectFileDataAttribute constructor, need to be marked obsolete #to-do

[[Songhay System Studio]]: “China’s Kling 2.0 stuns with Hollywood-level visuals: 7 compelling videos to watch”

KLING 2.0 Master comes with significant improvements in dynamics as it now offers more range of motion on the character subject with fluid movements and natural speed. The company claims that the new model comes with more dramatic expressions as seen in professional-level acting. It is offering more cinematic visuals and rich details even with text-to-video. The model allows for better style consistency with image to video enabling control over desired stylisation.

—“China’s Kling 2.0 stuns with Hollywood-level visuals: 7 compelling videos to watch

Kling AI 2.0 is HERE: The BEST AI Video Generator of 2025?

Kling AI 2.0 is HERE: The BEST AI Video Generator of 2025?

[[Songhay Player (C♯)]]: understanding the heart of the problem and memorializing this understanding in an integration test 😐🥣

The issue that evaded me for a week was about forgetting about the purpose of UpdatePlaylistItemContentDetailsAsync. This extension method is calling the [[YouTube]] API to download a "youtube#playlistItemListResponse" object in order to replace all of the items of this object with their corresponding "youtube#video" object. The purpose of this is to get more details about a given YouTube video (such as duration).

YouTubePlaylistItemsActivityTests.StartAsync_with_InputString_and_OutputString_Test now has the following assertions:

// assert:
Assert.NotNull(json);
JsonObject? jO = JsonNode.Parse(json)?.AsObject();
JsonArray? jA = jO?["items"]?.AsArray();
Assert.NotEmpty(jA?.OfType<JsonObject>()!);
Assert.All(jA?.OfType<JsonObject>()!, arrayItemObject => Assert.Equal("youtube#video", arrayItemObject["kind"]?.GetValue<string>()));

Had these assertions been in place a week ago—blah, blah, blah 😐

[[Netflix]]: “You Read That Right: We’re Introducing a New Way to Experience Subtitles”

Fifty percent of Americans say they watch content with subtitles most of the time. It’s a habit we see reflected on Netflix too—nearly half of all viewing hours on Netflix in the US happen with subtitles or captions on, so we’re making the experience even better for members.

—“You Read That Right: We’re Introducing a New Way to Experience Subtitles

open pull requests on GitHub 🐙🐈

sketching out development projects

Eliminating Angular JS in the Studio is the top priority. Replacing the Angular JS app (http://kintespace.com/player.html) for the kinté space depends on:

  • generating a new index.html page with eleventy
  • supplementing the index with responsive images

Proposed future items:

  • complete upgrade to .NET 8.0
  • replace current b-roll player API with Azure Functions
  • switch Studio Publications from Material Design to Bulma 💄 ➡️ 💄✨
  • start Songhay.Modules.Bolero.Index project
  • generate responsive and social images with AI

🐙🐈https://github.com/BryanWilhite/