add posts, edit posts

This commit is contained in:
jetstream0
2023-10-27 07:24:52 +00:00
parent cef4ed883f
commit 8f26ee6a89
6 changed files with 584 additions and 461 deletions

View File

@@ -7,6 +7,22 @@
"author": "jetstream0/Prussia", "author": "jetstream0/Prussia",
"tags": ["meta", "code", "project", "web", "markdown", "typescript_javascript", "css"] "tags": ["meta", "code", "project", "web", "markdown", "typescript_javascript", "css"]
}, },
"downloading-my-spotify-playlist-for-free": {
"title": "Downloading my Spotify Playlist for Free",
"slug": "downloading-my-spotify-playlist-for-free",
"filename": "downloading_my_spotify_playlist_for_free",
"date": "27/10/2023",
"author": "jetstream0/Prussia",
"tags": ["code", "typescript_javascript", "bash"]
},
"ryuji-rust": {
"title": "Ryuji Rust",
"slug": "ryuji-rust",
"filename": "ryuji_rust",
"date": "27/10/2023",
"author": "jetstream0/Prussia",
"tags": ["rust", "project"]
},
"llm": { "llm": {
"title": "LLM", "title": "LLM",
"slug": "llm", "slug": "llm",

View File

@@ -0,0 +1,74 @@
Like most people, I like listening to music.
Also like most people, I don't like listening to ads or paying subscriptions^\[0\]^. Spotify's free tier is pretty good, and I can block their ads by using the web player and uBlock Origin.
I'm mostly content with that, but there are still some annoyances - I can't listen offline, the UI is a little frustrating, and even though the ads are blocked, the player still sometimes freezes when an ad is supposed to be playing (so the next song isn't played, have to reload the page). Combined with not morally being a fan of relying on a for-profit third-party service for my music, I decided today to write a few scripts to download all the songs on my favourite Spotify playlist (around 60 songs).
First step is getting all the song and artist names on my playlist from Spotify. I did find an [Spotify API endpoint](https://developer.spotify.com/documentation/web-api/reference/get-playlists-tracks), but it seemed like a pain with OAuth required. Instead, I just opened the playlist in my browser. After scrolling down to load all the playlist tracks, I ran something similar to the following to get all the track names:
```javascript
[...document.querySelectorAll(".iCQtmPqY0QvkumAOuCjr")].map((d) => d.innerText)
```
After a bit of processing with Javascript, vim find-and-replace commands, and a few manual corrections, I ended up with a `songs.txt` file in this format:
```
1|Alice in Freezer|Orangestar
2|無人駅|n-buna
...and so on
```
Now that we have all the song and artist names, we need to fetch the Youtube urls of the songs, so we can download them with [yt-dlp](https://github.com/yt-dlp/yt-dlp).
It turns out the Youtube search API also needs an API key, so I used the [usetube](https://github.com/valerebron/usetube) npm package, which scrapes the actual web page instead of using the API. Here's the code:
```javascript
const fs = require("fs");
const yt = require("usetube");
async function main() {
let songs = fs.readFileSync("../songs.txt", "utf-8").split("\n");
for (let i = 0; i < songs.length; i++) {
let song_name = songs[i].split("|")[1];
let artist_name = songs[i].split("|")[2];
console.log(song_name+" "+artist_name);
const videos = (await yt.searchVideo(song_name+" "+artist_name)).videos;
songs[i] = songs[i]+"|https://youtube.com/watch?v="+videos[0].id;
console.log(songs[i].split("|")[3]);
}
fs.writeFileSync("../songs.txt", songs.join("\n"), "utf-8");
}
main();
```
Now `songs.txt` looks a little like this:
```
1|Alice in Freezer|Orangestar|https://youtube.com/watch?v=jQmYZWjLwzw
2|無人駅|n-buna|https://youtube.com/watch?v=G8PFPUCNOg4
...and so on
```
The final step is just writing a bash script to download all the songs. I don't really know much bash, but after a few StackOverflow searches, I got a working script:
```bash
#!/bin/bash
while IFS= read -r line; do
IFS='|' read -ra ADDR <<< "$line"
for i in "${!ADDR[@]}"; do
printf "\n${ADDR[$i]}"
if [ $i -eq 3 ]; then
yt_dlp -x --audio-format mp3 "${ADDR[$i]}"
fi
done
done < songs.txt
```
Yay!
This was a pretty "boring" project that didn't involve much thinking or code. But being able to automate small, tedious stuff like this is a pretty underrated perk of having even a little programming knowledge.
===
- \[0\]: It's almost like artists are people too, and need to make money to support themselves! In all seriousness though, Spotify pays artists something like $0.003 USD per stream. It makes much more sense to support them through buying albums or going to concerts, instead of wasting time listening to ads.

View File

@@ -179,6 +179,9 @@ npm run test
``` ```
## Todo ## Todo
In the future, I would love to have those fun box gifs you used to see on geocities and other websites (like the ones on the bottom of the [pensquid](https://pensquid.net/) website), plus also something similar to [Wikipedia Userboxes](https://en.wikipedia.org/wiki/Wikipedia:Userboxes). In the future, I would love to have those fun box gifs^\[0\]^ you used to see on geocities and other websites (like the ones on the bottom of the [pensquid](https://pensquid.net/) website), plus also something similar to [Wikipedia Userboxes](https://en.wikipedia.org/wiki/Wikipedia:Userboxes).
And I'll keep improving the site and fixing bugs, and occasionally write articles for the roughly four readers of this blog. And I'll keep improving the site and fixing bugs, and occasionally write articles for the roughly four readers of this blog.
===
- \[0\]: This has been done! Plus, there's a [RSS feed](/posts/rss-feed) now too.

5
posts/ryuji_rust.md Normal file
View File

@@ -0,0 +1,5 @@
A month or two ago, I "translated" [Ryuji](/posts/ryuji-docs), originally written in Typescript, into Rust.
I mostly wrote this to practice writing Rust, which I guess is a success. In this project, I've somehow once again avoided properly figuring out how to use lifetimes (hey, I tried). That's a victory for my brain but probably a failure for my Rust skills.
The source code is on [Github](https://github.com/jetstream0/ryuji-rust) and the auto-generated documentation is on [docs.rs](https://docs.rs/ryuji-rust/latest/ryuji_rust/). If, for whatever reason, you actually want to use Ryuji-Rust, it might be helpful to look at the [tests](https://github.com/jetstream0/ryuji-rust/blob/master/src/lib.rs), [example](https://github.com/jetstream0/ryuji-rust/tree/master/example), and the [Ryuji docs](/posts/ryuji-docs) page.

View File

@@ -1,3 +1,5 @@
> **Update, October 2023**: I realize I was being kind of an idiot. In retrospect, what I should've done was have the MongoDB operation be a `replaceOne` that *only* modifies if the damage dealt is under the hp - so it would only be possible for a write to happen for one player even if two click at the same time. Then, I could check the return value of the `replaceOne` (which tells me whether the operation modified documents or not), and discard any fake winners whose clicks did not result in the database being modified. Beware that if you continue reading, you will encounter a very stupid solution to a problem.
Recently, I've been working on a discord bot game for Beer Goggles NFT on Algorand. Recently, I've been working on a discord bot game for Beer Goggles NFT on Algorand.
The specifics aren't too important, but essentially the game works like this: A game is started by an admin, and a secret number of hp is specified. Then, players can click a button, and depending on the amount of NFTs they hold, they will do "damage". All the damage is added up, and the person who crosses the secret number of hp wins. Like a pinata. Or in the case of our bar themed game, a huge opaque mug of beer that is passed around, with the goal being the one to finish the drink. The specifics aren't too important, but essentially the game works like this: A game is started by an admin, and a secret number of hp is specified. Then, players can click a button, and depending on the amount of NFTs they hold, they will do "damage". All the damage is added up, and the person who crosses the secret number of hp wins. Like a pinata. Or in the case of our bar themed game, a huge opaque mug of beer that is passed around, with the goal being the one to finish the drink.
@@ -17,5 +19,3 @@ What did work though, is adding a random delay using `setTimeout` and `Math.rand
Technically, if the random delay was the same or only a few milliseconds different, the global variable could be looked at the same time, and two winners (or more) could still be announced. Technically, if the random delay was the same or only a few milliseconds different, the global variable could be looked at the same time, and two winners (or more) could still be announced.
... let's not worry about that ... let's not worry about that
> (A quick update: in several dozen games, after the fix, the two winner situation never happened again. It wasn't elegant and it was a dumb solution, but it worked! Maybe there was a better solution by fiddling with the database settings, like making database calls queue one at a time?)

View File

@@ -132,3 +132,28 @@ Here's a very incomplete (and maybe actively updated) list of ones that led to m
- [Kurt Gödel](https://en.wikipedia.org/wiki/Kurt_G%C3%B6del), mathematician - [Kurt Gödel](https://en.wikipedia.org/wiki/Kurt_G%C3%B6del), mathematician
- [Joe Hill](https://en.wikipedia.org/wiki/Joe_Hill_%28activist%29) - [Joe Hill](https://en.wikipedia.org/wiki/Joe_Hill_%28activist%29)
- [Dual_EC_DRBG](https://en.wikipedia.org/wiki/Dual_EC_DRBG), a (probably) NSA backdoored random number generator - [Dual_EC_DRBG](https://en.wikipedia.org/wiki/Dual_EC_DRBG), a (probably) NSA backdoored random number generator
- [English-based creole languages](https://en.wikipedia.org/wiki/English-based_creole_languages)
- [Austro-Hungarian concession of Tianjin](https://en.wikipedia.org/wiki/Austro-Hungarian_concession_of_Tianjin)
- [Steve Mann (inventor)](https://en.wikipedia.org/wiki/Steve_Mann_%28inventor%29), inventor of wearable computing technology
- [Kronstadt rebellion](https://en.wikipedia.org/wiki/Kronstadt_rebellion), revolt against the Bolsheviks by Soviet soldiers
- [Great Purge](https://en.wikipedia.org/wiki/Great_Purge), Stalin purges a lot of people
- [Iranian Revolution](https://en.wikipedia.org/wiki/Iranian_Revolution)
- [Cultural Revolution](https://en.wikipedia.org/wiki/Cultural_Revolution), which didn't turn out very well at all
- [National Treasure (Japan)](https://en.wikipedia.org/wiki/National_Treasure_%28Japan%29)
- [Protozoa](https://en.wikipedia.org/wiki/Protozoa)
- [Akira Kurosawa](https://en.wikipedia.org/wiki/Akira_Kurosawa), filmmaker
- [Isle of Man](https://en.wikipedia.org/wiki/Isle_of_Man)
- [Fantastic War](https://en.wikipedia.org/wiki/Fantastic_War), fought between Spain and Portugal as part of the [Seven Years' War](https://en.wikipedia.org/wiki/Seven_Years%27_War). Was not fantastic for Spain, since they lost
- [Nikoli](https://en.wikipedia.org/wiki/Nikoli_%28publisher%29), publisher of puzzle gmaes like Sudoku
- [Sikkim](https://en.wikipedia.org/wiki/Sikkim)
- [Subutai](https://en.wikipedia.org/wiki/Subutai), Mongol general who invaded Hungary
- [Free speech fights](https://en.wikipedia.org/wiki/Free_speech_fights), usually suppression of labour issue related speech
- [Sesshū Tōyō](https://en.wikipedia.org/wiki/Sessh%C5%AB_T%C5%8Dy%C5%8D), painter
- [Java War (17411743)](https://en.wikipedia.org/wiki/Java_War_%281741%E2%80%931743%29)
- [Tuareg people](https://en.wikipedia.org/wiki/Tuareg_people)
- [Amnesty International](https://en.wikipedia.org/wiki/Amnesty_International)
- [Julian Assange](https://en.wikipedia.org/wiki/Julian_Assange)
- [Bukharian (Judeo-Tajik dialect)](https://en.wikipedia.org/wiki/Bukharian_%28Judeo-Tajik_dialect%29)
- [Qt (software)](https://en.wikipedia.org/wiki/Qt_%28software%29), for developing GUIs
- [Sailfish OS](https://en.wikipedia.org/wiki/Sailfish_OS)
- [SerenityOS](https://en.wikipedia.org/wiki/SerenityOS)