Tilde Town Autowaterer

I was browsing, surfing and searching when I stumbled upon tilde.town. Of course I got an account, it's a charming project. I especially love the town commands, never have I ever seen such level of community interactivity.

Let's Plant a Plant

One of such commands is town botany. It's a lovely little project where you raise your plant. Sadly, I've realized I am going on vacation soon and my plant would suffer. I couldn't let that happen! I started searching how to help the little byte organism.

Reverse-Engineering The Plant

The project sits at Github - jifunks/botany. It's a couple of python files, so it's right up my alley. You'll learn that there's a central sqlite database and your client. Fortunately for us, the database trusts the client - so if you substitute your own client you can modify the state.

The client saves the data in two files:

  • a json file - ~/.botany/username_plant_data.json
  • a pickle file - ~/.botany/username_plant.dat

It's enough to modify the pickle file username_plant.dat. To do that, you'll need the original plant.py from the Github repo. You'll find there's a var named watered_timestamp. Put the current time here and your plant is watered!

Well, almost. You need to run the client with this modified plant so it writes the data to the db. And since it uses curses, you can't just put it in a crontab (learned that the hard way).

So one last dive into the source code, fortunately the DataManager class is independent on curses interface, so all I have to do is to call it.

Scripting The Watering

This is how you put the ideas together:

#!/usr/bin/env python3

# This scripts automatically waters your `town botany` plant.
# get https://github.com/jifunks/botany/blob/master/plant.py
# put that file in the same dir for unpickling
# get https://github.com/jifunks/botany/blob/master/botany.py
# put that file in the same dir, remove the `import menu_screen as ms` line
# Schedule the script into a cronjob, e.g. 1 1 * * * /home/user/town_botany_autowaterer.py
# Enjoy your plant!
#
# ~hariogrindset

username = "hariogrindset" # enter your username

import plant
from botany import DataManager
import pickle
import json
import math
from time import time, sleep
import subprocess
import os
import getpass
import threading
import errno
import sqlite3

plant_dir = f"/home/{username}/.botany/" # assuming you have it in your home dir /home/username/
plant_pickle = plant_dir + username + "_plant.dat"
plant_json =   plant_dir + username + "_plant_data.json"

with open(plant_pickle, 'rb') as f:
    pp = pickle.load(f)

# print(vars(pp))
# print(pj)

# pour the water!
pp.watered_timestamp = math.floor(time())

with open(plant_pickle, 'wb') as f:
    pickle.dump(pp, f)

# open the client to handle everything
dm = DataManager()
dm.save_plant(pp)
dm.data_write_json(pp)
dm.update_garden_db(pp)

All that's left is to setup a cronjob, so that your plant is watered periodically. You can do it like so:

0 0 * * * /home/username/town_botany_autowaterer.py

My Plant Is Saved

This was fun. I've also shared the source within tilde.town so that other plants can survive. It's only possible because there is no integrity/signature check on a modified file. Such a lovely project, so full of joy.