Daniel's Weblog
Posts Tags Colophon
About

Jul 19, 2025


Uploading an entire directory to the Internet Archive: I had a collection of files around ~50 GB in size that I wanted to upload to a single item in the Internet Archive directly from my NAS. There is a cli that could work but didn’t have a trivial way to upload all the files in a directory. I tried the S3-compatible endpoint with Cyberduck but that also didn’t work as expected.

I ended up running the Python library in a detached tmux session.

# In Bash:
python3 -m venv venv;
source venv/bin/activate;
pip install internetarchive;

# In Python:
from internetarchive import upload
upload(
    'DESTINATION_ITEM_ON_INTERNET_ARCHIVE',
    'LOCAL_FOLDER/',
    # After creating an account you can ge the required keys here:
    # https://archive.org/account/s3.php
    access_key='YOUR_ACCESS_KEY',
    secret_key='YOUR_SECRET_KEY'
)

Note: Remember, uploading things to the Internet Archive makes the email address associated with your account publicly visible


Jun 28, 2025


Geotagged videos of the L Train Brass Band in the Mermaid Parade My friend collected all of the YouTube videos that include the L Train Brass Band in the 2025 Coney Island Mermaid Parade and I’ve placed them on a map!

Clicking on any dot will bring up the relevant YouTube video at the timestamp the band goes by. It’s pretty crude at this point. I didn’t place the markers very carefully and some are stacked on top of each other. The green dot represents the start and the red dot the end.

This set up would work techincally for any other event but the Mermaid Parade is a little unique in a way that makes this easier. It’s a short parade and many people film it meaning there are many videos that include the entire parade. The scenery along the route is also very recognizable making manual geotagging easy.


Jan 17, 2025


Songs of Lehigh (vol 2)

01
Klaxon
3:10
02
Victory March
1:26
03
Sunset in Bethlehem
0:54
04
Rearin' Tearing
0:53
05
Hail to Lehigh
1:14
06
Goblet
0:54
07
Campus Dreams
2:13
08
Men of Lehigh
1:60
09
Alma Mater
2:48
10
Noble Men
2:16
11
Hoo-Rah-Ray, Lehigh!
0:17
12
Cheer for Alma Mater
0:29
13
Lehigh's Loyal Sons
0:48
14
O LaFayette, Poor LaFayette
0:46
15
Cliff-Clef Riff
1:24
16
Rise 'N Shine
0:54
17
I Can't Believe
2:70
18
Paper Moon
1:17
19
Tea for Two
2:13
20
Til We Meet Again
1:19
21
2022-04-17 Situation
46:43
Hosted by the Internet Archive

Songs of Lehigh 1948-49 (vol 2) My quest to acquire and digitize all of the Lehigh University vinyl records continues.

This is now my second undated Lehigh vinyl. We could probably pin down the year by contacting the admissions department but it’s a good reminder to date your work!

Update, 2025: I found some info on a website called Worthpoint which seems to reproduce listings from online stores that indicates that this is disk two of a three disk set from 1948-49!

I’ve reproduced the reproduction here for future reference:

Excellent vintage condition. Some damage to the outer case binding and to one of the record sleeves (small split at bottom). Outer case has some scuffs and stains consistent with age of the item.

Set of three 10 inch 78 speed albums featuring the Lehigh Glee club dating to the late early 1950s. Packaged in a very nice bound book-style cover. Includes the following songs:

Side 1 - Campus Dreams, Spirit of Lehigh, Sunset in Bethlehem
Side 2 - Animals a’comin, Lehigh-Ho, Alma Mater
Side 3 - Hail to Lehigh, Victory March, Cheer for Alma Mater, Lehigh’s Loyal Sons
Side 4 - Beer Song
Side 5 - Boolia Boshka (featuring Moravian College for Women Singers)
Side 6 - This I Have Wanted to Hear (featuring Moravian College for Women Singers)

This is a part of a series where I digitize vinyl records. More Lehigh records / all records!


Aug 27, 2024


Whiteface Mountain and Mount Esther

Scroll for more →

Dec 29, 2023


Grandpa hiked Mount Marcy in 1955. After hiking Mount Marcy twice myself I recognized where one of the pictures was taken.

Grandpa’s original photo, a lone hiker with backpack looks across Marcy Dam Pond up at Mount MarcySimulated terrain view of the location of the original picture from Google EarthGoogle Maps terrain map

Marcy Dam was damaged by Hurricane Irene in 2011 and the dam has since been removed (Wikipedia).

The same view in 2019:

View in 2019

Oct 10, 2023


SSH to server via Tailscale if possible: If Tailscale is not running fall back to a different IP

Requirements:

  • Tailscale installed via Mac App Store
  • jq installed via Brew

Replace the following values: {SERVER_NAME}: These configuration options will be used when you type ssh {SERVER_NAME} {SERVER_USERNAME}: The username you use to connect to the server {SERVER_TAILSCALE_IP}: IP Address or DNS name {SERVER_NON_TAILSCALE_IP}: I said “IP” but “hostname” will also work here {SERVER_PRIVATE_KEY_FILENAME}: Private key to log in with

# If Tailscale is running connect via this:
Match originalhost {SERVER_NAME} exec "[ $(/Applications/Tailscale.app/Contents/MacOS/Tailscale status --json | jq -r .BackendState) != Stopped ]"
    HostName {SERVER_TAILSCALE_IP}
    User {SERVER_USERNAME}
    IdentityFile ~/.ssh/{SERVER_PRIVATE_KEY_FILENAME}

# If Tailscale is not running connect via this:
Host {SERVER_NAME} 
    HostName {SERVER_NON_TAILSCALE_IP}
    User {SERVER_USERNAME}
    IdentityFile ~/.ssh/{SERVER_PRIVATE_KEY_FILENAME}

Sep 17, 2023


POPS - Lehigh University

1
Salute to Lehigh University
1:29
2
Pride of the 97
2:17
3
Centennial Song
1:36
4
Commando March
3:28
5
Irish Tune From County Derry
3:40
6
Shepherd's Hey
2:10
7
The Sinfonians
5:90
8
March
4:35
9
Song With Words "I'll Love My Love"
2:17
10
Song of the Blacksmith
1:18
11
Fantasia on the "Dargason"
3:60
12
Porgy and Bess
10:54
01
Lehigh University - POPS - Raw audio
43:58
Hosted by the Internet Archive

Pops by the Lehigh University Band Another Lehigh vinyl acquired and now available on Archive.org. From discussion in the Marching 97 alumni band Facebook group we’ve learned the following:

  1. “Pops used to be the spring concert for Wind Ensemble, IIRC”
  2. “Jim Brown was a faculty member at Lehigh from 1973 to 1979. So, this record probably came from mid 70’s”

This is a part of a series where I digitize vinyl records. More Lehigh records / all records!


May 19, 2020


Opening Signal Desktop Database on MacOS: I’ve seen some conflicting processes out there, here’s what worked for me in May, 2020:

  1. Download and install DB Browser for SQLite but note that YOU MUST download the version specifically built with SQLCipher support. This version is not obviously available on their website, but you can find it in the nightly build folder here

    When I tried to open the database with the default version of DB Browser it asked for a key or passphrase but it was never successful in decrypting the database. (This was what you might call infuriating)

    You can find those builds here: nightlies.sqlitebrowser.org/latest

  2. Open the folder in Finder by pressing Shift + Command ⌘ + g (or open the Window menu and click Go to Folder) and enter the following path:

    /Users/{USERNAME}/Library/Application Support/Signal

  3. Open the file config.json in your favorite text editor and copy the value of key, for if you saw the following you would copy A_VERY_LONG_STRING_OF_LETTERS_AND_NUMBERS without the quotation marks.

    {
      "window": null,
      "key": "A_VERY_LONG_STRING_OF_LETTERS_AND_NUMBERS",
      "mediaPermissions": true
    }
    
  4. Back in Finder open the folder sql

  5. Open the file db.sqlite (by right clicking on the file and pressing open as, dragging the database to the application, etc.) in your newly installed version of DB Browser for SQLite.

  6. Switch the decryption method from passphrase to raw key in the dropdown menu

  7. Ensure that SQLCipher 4 Defaults is checked. SQLCipher 3 Defaults did not work for me.

  8. Type 0x in the password box and then paste the key you copied from config.json.

  • With our previous example you would enter 0xA_VERY_LONG_STRING_OF_LETTERS_AND_NUMBERS
  1. Press OK

You should be in, the rest is up to you!


Jan 24, 2019


A small recipe for combining WTForms and the Quill text editor: I’m using Flask-WTF so this isn’t exactly the same as a pure WTForms implementation, but it should get anyone else on the right track.

The Quill text editor defines its contents as a delta object.

“Don’t be confused by its name Delta—Deltas represents both documents and changes to documents.”

When a user submits the “save changes” button we can use the Quill API to access the contents of the text editor, serialize it with JSON.stringify(), put that string in a WTForm field, which then gets submitted to the backend. In order to keep the form nice and clean we can hide that field from the user.

forms.py

  • The first hidden field is called “delta”, which holds the serialized contents of the delta object.
  • The second hidden field is called “length” which holds the length of the actual content in the delta object.
from flask_wtf import FlaskForm
from wtforms import SubmitField, HiddenField, IntegerField
from wtforms.validators import Length, NumberRange
from wtforms.widgets import HiddenInput

class CreatePost(FlaskForm):
    delta = HiddenField(
        'delta',
        validators=[Length(0, 255)],
    )
    
    content_length = IntegerField(
        label='',
        validators=[
            NumberRange(2, 255, "Blank posts aren't very interesting.")
        ],
        widget=HiddenInput()
     )
     
    submit = SubmitField('Create Post')

template.html

This flask template takes an argument named “form” containing a CreatePost object (defind in the example code above).

{% block page_content %}
<div class="row justify-content-center">
  <div class="my-sm-2">
    <div class="page-header">
      <h1>Read a Post</h1>
    </div>
    <!-- Create the editor container -->
    <div id="editor">
      <p>Hello World!</p>
      <p>Some initial <strong>bold</strong> text</p>
      <p><br></p>
    </div>

    <!-- 
    Form submission is handled by FlaskWTF. It has a hidden field, which
    is updated with the contents of quill.getContents() when the submit
    button is pressed
    -->
    {{ render_form(form) }}

    <!-- Include the Quill library -->
    <script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>

    <script>
	   // Initialize the Quill editor
      var quill = new Quill('#editor', {
        theme: 'snow'
      });

      // When the submit button is pressed, retrieve several pieces of info
      // from the QuillJS API (https://quilljs.com/docs/api/#content), copy
      // them into to WTForms hidden fields, and submit the form
      var submit_entry = function () {
      
        // Get the contents of the text editor
        var hidden_text_field = document.getElementById('delta');
        hidden_text_field.value = JSON.stringify(quill.getContents());
        
        // Get the length of the contents of the text editor
        var hidden_length_field = document.getElementById('length');
        hidden_length_field.value = quill.getLength();
      }

      // Attach the onclick function to the submit button Flask-WTF creates
      var new_post_form = document.getElementsByClassName('form')[0];
      new_post_form.onsubmit = submit_entry;

    </script>
  </div>
</div>
{% endblock %}

Dec 13, 2018


Temperature Sensors Part 5: Assembling PCBs & Future Plans

I finally received my printed circuit boards in the mail, time to assemble them.

This is post number 5 in a series describing my DIY temperature and humidity sensors.

Printed Circuit Boards

OSH Park’s packaging is not subtle.

The boards are indeed a dark purple, which my camera didn’t properly capture. Here’s what they look like unpopulated and populated:

On the top right there’s a little bit of what I can only assume is someone else’s screen printing that overlapped on to my board. No harm done, and it adds character. The little points that held the panel together during production are rather sharp, I ended up cutting off the points so I wouldn’t stab myself.

It’s not perfect, though. The empty space between components is smaller than it seemed on the computer screen and I didn’t leave enough space between the components. I had to tilt headers connecting to the temperature sensor so it would fit along side the ESP8266.

Despite that, it’s definitely an improvement over the hand-made version.

Future Plans

So where to go from here? I’ve been using this for temperature sensors, but in reality I’ve created a 3.3V based I²C base for the ESP8266. I could replace the temperature sensor with…

  • Another atmospheric monitoring sensor with barometric pressure as well
  • An infrared array to determine if a human (or dog, maybe?) is present
  • A 16x2 LCD Display that could easily update over Wi-Fi
  • A Sparkfun Qwicc Adapter so I can daisy-chain many I²C sensors together (An external power supply may be required, depending on how crazy you want to get)

But it doesn’t have to be limitted to I²C interfaces!

  • I’ve been thinking about using a non-invasive current sensor so I don’t have to walk all the way to the basement to check on the washer and dryer
  • A particulate matter sensor so I can detect air polution hazards (like if my housemate is cooking extremely spicy chicken)
  • Or even something as simple as a reed switch to tell if a door is open