17
Dispatch → Bulletin → News
WILD LIFE - January 2023
Woosh! Another year of inactivity just flew by. Which is why I'm partly responsible for the demise of NS Today. Real-life pressures and all that. Not that my real-life pressures are as ridiculous as this real-life story. While most of NS-related 2022 passed me by, I did manage to spot some technical happenings. And for those of you nervously watching out for snakes, that python is here.
But if you're just thinking, "I don't care about any of this. Why did I get a notification?", then this section is for you.
Early in 2022 I'd taken on the role of Chief Content Officer with NS Today. It had been a promising start, with good ideas for articles, and keen writers working on stories. With editing, quality controls, and chasing up people to complete tasks, doing it properly was very like having a job. Which should have been fun. Except I already had a full time job. And that day job was getting more demanding. Sadly, real-life won out over NS (it pays better), and I had to step back from NS Today.
I was far from being the glue that held NS Today together. The staff were all talented individuals who could continue perfectly well without me, as evidenced by Vulshine's third-in-the-series roleplay constitution article, and SkyGreen's piece on Sanctum. However, people committing less puts more pressure on the rest, making it more difficult for them to continue. And so gradually NS Today came to a halt.
In November, Lewis (the co-founder, and the former Chairman and Chief Executive of NationStates Today) made this announcement on Discord:
@Notifications After a review of the activity over the last 3 months, and following a warning I gave to the Board, I have decided to stop providing funding for the NationStates Today website.
The annual cost to me is now over $80, which just isn't sustainable for a dormant project.
I have generated a static backup version of the website, which is now permanently available here: https://nationstates.news/
NationStates Today should therefore be considered in a dormant state. Thank you for all of your support over the last few years. It's been fantastic.
If anyone is interested in taking over the project, please send me a message. I have the archives of the website, etc.
Thanks again :)
You must have seen this in the mainstream press. But I loved this story, so I'm recycling it here. And if you're wondering what NSG thought, here's the place to start.
The premise for Repeal or No Repeal is pretty simple. A recently passed piece of legislation gets named, and you have to guess correctly as to whether it will be repealed before the end of the month.
It's quite some time since Daarwyrth's legislation, Protections During Territorial Transitions passed with 64.9% in favour! I asked if it would get repealed before 1st October. Well, the legislation outlived Daarwyrth, who CTEd in December! Hopefully issues author Daarwyrth will be back with us at some point in the future.
Tinhampton, Toonela, Large Ladz, The Orwell Society, St Saratoga, The North Polish Union, Voljundok, Daarwyrth, Aleixandria, Life empire, Mauryavarsha, Kanteen
In Tech news, NationStates is catching up with the 21st century. Wait, what? NS was created in the 21st century? Huh. Who knew? Anyway... there's now an official NationStates Announcements Channel for Discord. This way we can get pinged with the information that NS is broken rather than discovering for ourselves when we try to log in. That's a massive step forward, right? Right?
Talking of NS being broken, addicts were served some cold turkey for Christmas when the site went down. If you missed it, you'll be glad to know that photo-journalist Cataleenia had their camera handy and documented events. [WARNING: link contains full-frontal nudity of a moderator]
Back in August, the site took on five new Technical Moderators, namely Chingis (who, iirc, was largely responsible for infecting NS with a nasty dose of crabs, and whose Buzzy Bee ensured that Lily got pollenated across hundreds of regions each update), Esternial (of P2TM fame), Racoda (notorious card-sharp and industrial farmer), Roavin (whose typical post in Technical contains more knowledge than my entire brain), and United Calanworie [Aav] (whose technical magic kept NS Today hanging together).
Understandably these appointments caused some excitement (and possibly some overexcitement). Nearly everyone was positive about the news, except for one very weird threadjack. And while we've not seen much new yet the technical pipeline looks promising, with Aav letting us know suggestions for BBCode improvements are being looked at (and who wouldn't want those?), and Roavin gathering ideas of improvements that script authors would like to see.Ah yes. And script authors may wish to look away. Coming up next is what might be best described as a script crayon scribble!
You poured the last of your favourite cereal from the packet into your bowl. You took the milk out the fridge and poured that in too. Then you noticed the milk was out of date. The milk *smells* like it's OK. But is it? How long past the Use By Date could the milk be before you'd throw out this cereal?
It's official - over half of us think that a morning sugar-rush outweighs the risk of an all-day toilet rush!
Ejoland, Insane cookie browser, All Wild Things, Tiger 237, Aleixandria, Wild panther, Choccolate, Lower crimea, Natord dommaniaordia, Kharim, Jewish sealand, Vipru, The Hurricane, Doranbia, Happiville
I've been intending to learn a bit about the Python coding language for a few years now. It's getting used more and more at my work, so it's potentially useful for me there. While I'm not entirely new to coding (I learned a bit of Visual Basic on the job, and have played with Javascript in the past), professional Javascript developers have seen my code - and despaired. I imagine anyone familiar with Python will similarly cringe at my attempts here. If that's you, look away now! What follows is not a guide on how to code Python. It's just a warts-and-all record of the terrible hacks I'm doing to make some stuff work with NationStates.
To start, I visited https://www.python.org/downloads/, and downloaded Python 3.11.1 (the latest version) onto my Windows laptop. The download included a basic development environment, and that's what I've been using to write some code. There will be much better IDEs out there that are free to download and use, but this one will do me for now.
After acing the traditional "hello world" project, I thought I'd move on to an NS themed script. Why do anything inbetween, right?
NationStates has strict rules about how our code / scripts can interact with it. Keep to those rules. They're linked from the Technical forum, and can be found with the API documentation: pages/api.html.
For my first NS Python project, I thought I'd keep it simple, and make a single API request to get some data about my nation. It could have been simple. It should have been simple. But I found a way to complicate it.
It started off not too bad. From the NS API documentation, I easily figured out that the URL that would return my nation info was cgi-bin/api.cgi?nation=all_wild_things.
If you click on that link, your browser should open a tab showing XML with my nation's data. But I don't want to be looking at the data in a browser - I want it in my app so that I can manipulate it in hideous ways.
Google told me that the "requests" Python module would allow me to make an API call. So I needed to install that module. I opened a command prompt, and typed "pip install requests". Astoundingly, it worked first time, and installed the module. So I then copied some example code from the net into a new Python script, and modified it to make it work for me:
import requests def fMain(): objResponse = requests.get( 'https://www.nationstates.net/cgi-bin/api.cgi?nation=all_wild_things', headers={"User-Agent": "smalldickenergy@getalife.com"} ) print("Status:", objResponse.status_code) print("Headers:", objResponse.headers) print("Text:", objResponse.text) fMain()
The "requests.get" command opens up a connection to NS, sends my headers, assigns the response to my "objResponse" variable, then closes the connection again. I can then work with different properties of objResponse. NS asks that API users include a User-Agent in the headers so that they can contact you if your script is messing with the site. If you use this code, make sure you change the User-Agent to your own email address, and not Greta's.
The script outputs three attributes of objResponse. "Status" is the HTTP status code. If the API request works properly, I should get status code 200 back, indicating a success. If ever there's a problem with the API request, the status code should help indicate what went wrong. "Headers" are meta-info that NS has sent back about the API request. And "Text" is the XML data that I requested.
It's worth noting some of the coding habits that were beaten into me in the past. Different languages have different conventions. I generally ignore them, and stick with what I was taught. The function is called "fMain" instead of just "Main". The small-case "f" is a reminder that this is the name of a function. Similarly the variable "objResponse" gets prefix "obj" to indicate that it's some sort of object. I use variable name prefixes such as "int" for integers, "str" for string etc. This isn't recommended by Python, it's just what I do. In Python, you can change a variable's type from integer to string etc, so this habit may well backfire if I need to do something like set intRowNumber = "John".
The code worked. It brought back the data I wanted it to. Yes, the output format looked like garbage, but finessing that is a job for another day. So I reckoned that was a win. Except that the API call was synchronous.
Which needs an explanation. With a synchronous request, NS gets asked for the data. And nothing else happens until the data is returned and it gets processed. With an asynchronous request, NS gets asked for the data, the code can do some other stuff, and then when the data gets returned it gets processed. For a simple script like this, it makes no difference. And since NS is rate-limited to 50 API calls per 30 seconds, it probably makes little difference even for more complex code. But being bloody-minded, I wanted to figure it out. And figuring out how to do that was a bit of a headache.
I don't remember if I had to install the asyncio module, but I definitely needed to install aiohttp ("pip install aiohttp"). Then after much staring at examples, and trial-and-error, I came up with this code:
import aiohttp import asyncio async def fGet(objSession, strUrl, dictHeaders): async with objSession.get(strUrl, headers=dictHeaders) as objResponse: return objResponse.status, objResponse.headers, await objResponse.text() async def fMain(): async with aiohttp.ClientSession("https://www.nationstates.net") as objSession: intStatus, objHeaders, strText = await fGet( objSession, "/cgi-bin/api.cgi?nation=all_wild_things", {"User-Agent": "smalldickenergy@getalife.com"} ) print("status: ", intStatus) print("headers: ", objHeaders) print("text: ", strText) asyncio.run(fMain())
That's a lot more code for the same output. In this one, function fMain creates an object objSession. This is the thing that connects to NS. Unlike the "requests" module, this can keep the connection open, which in theory makes it more efficient for making multiple requests. But I suspect that due to the rate limit, this won't improve any NS code performance. I also specified the base NS URL when defining objSession. It doesn't actually need specified at this point, but apparently it makes the thing even more efficient. And when I call my fGet function, I only need to send the second part of the long URL I'm wanting the data from.
I've got a separate function, fGet, which actually sends my URL and headers to NS and retrieves the data. The "status" and "headers" get sent back by NS almost straight away. The "text" takes a little longer, which is why the "await objResponse.text()" is needed. Because the information comes back at different times, this is possibly where a few milliseconds of efficiency gains can be made - the status & headers can get processed while waiting on the text. But I'll see what I can do with that another time.
You will have received a notification if you have been mentioned somewhere in this dispatch, and have a tick in the "Dispatch mention" box of your subscriptions page.
Almost all nations mentioned will have:
- done something I felt was worth writing about in an article
- voted in a recent not-so-recent Where The Wild Things Are poll
If you would prefer not to be notified in future, your choices are:
- Stop doing cool stuff worth writing about
- Don't interact with our RMB or polls
- Un-tick in the "Dispatch mention" box of your subscriptions page
But hopefully you enjoyed this dispatch, and don't mind the ping.
If you would like to subscribe, please post the word 'Subscribe' on Where the Wild Things Are RMB, or send me a TG, and I'll take a note to ping you next time.
Aleixandria, Davelands, Indusse, Jeeves Land, Napaqaq, Of Altonianic Islands, Pathoal, Ricore, Sky point, St Saratoga, The Georgeian Empire, The Orwell Society