💾 Archived View for tilde.club › ~mowlawner › gemlog › 20240607.gmi captured on 2024-08-18 at 17:45:23. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2024-06-20)

-=-=-=-=-=-=-

Botany Automation

2024-06-07

----------------------

UPDATE 2024-06-19

It seems I got it working. I've updated my .py files and added a script to call Botany and immediatly close it afterwards. This reads the visitors.json file and waters the plant.

----------------------

UPDATE 2024-06-12

It seems to work like a charm now. Not sure if it's because I changed something or not.

Anyway it's totally possible while tinkering with trying to call Botany from the watering script to force refresh the water status I caused it to stay open in the background and I'm not sure how to close it again - IF that is what happened...

-----------------------

-----------------------

UPDATE 2024-06-10

My scripts do not seem to work. I don't fully seem to understand how the watering works.

I'll keep the post as a reference :)

-----------------------

Since I'm new to this whole shared server thing I keep discovering new things.

One of the new things is Botany, a small game where you have to water a plant. It's also possible to visit and water someone else his plant.

I've seen gemlogs with a link to water the plant so obviously I wanted this too so my visitors can help keeping my plant alive.

Finding documentation on how to do this was pretty hard and I don't have enough developer experience (or time) to go over the entire code in the Github repo. I started tinkering and found several JSON files in the .botany folder in my home folder.

visitors.json seems to be a log of who visited your plant. After some experimenting it seems that it gets cleared from time to time. I suspect that this is when the app checks and then waters the plant and clears the log.

username_plant_data.json seems to be the status of the plant. It also appears not to be live, but rather a snapshot of the plant status.

username_plant.dat seems like a data file with your plant's actual data but does not seem to be easily readable.

I read that we could write server side scripts on gemini so I started in python. My python is pretty rusty since it's about 4 years ago I did anything with it so please don't judge. I'm also not a developer but rather a sysadmin with some scripting experience.

These scripts seem to work, but not a 100% of the time. I'm not sure whether it's because of browser caching or my logic is failing me.

Scripts

Script to fetch and display my plant's status

#!/usr/bin/python3
import json
import time
from datetime import datetime

print("20 text/gemini",end="\r\n")
print("This is my plant. It stays alive by giving it water atleast once in 5 days. Please help me keeping it alive by watering it!")

plantFile = open('/home/mowlawner/.botany/mowlawner_plant_data.json')
plantData = json.load(plantFile)

lastWateredtime = datetime.fromtimestamp(plantData['last_watered'])
lastWaterTimeDiff = datetime.now() - lastWateredtime
lastWaterDaysAgo = lastWaterTimeDiff.days
lastWaterSecondsAgo = lastWaterTimeDiff.seconds

lastWaterHours = lastWaterSecondsAgo // 3600
lastWaterMinutes = (lastWaterSecondsAgo % 3600) // 60
lastWaterSeconds = lastWaterSecondsAgo % 60

print(f"'''")
print(f"Description: " + plantData['description'])
print(f"Age: " + plantData['age'])
print(f"Last watered: {lastWaterDaysAgo}d {lastWaterHours}h {lastWaterMinutes}m {lastWaterSeconds}s ago.")
print(f"Stage: " + plantData['stage'])
print(f"Generation: " + str(plantData['generation']))
print(f"Score: " + str(plantData['score']))
print(f"'''")
print(f" ")
print(f"=>      waterplant.py   🪴💦Water my plant to keep it alive!")
print(f"=>      index.gmi       🏠Back to my capsule")
plantFile.close()

Script to actually water my plant

#!/usr/bin/python3
import json
import time
import subprocess

print("20 text/gemini",end="\r\n")
visitorFilePath = '/home/mowlawner/.botany/visitors.json'

with open(visitorFilePath, 'r') as visitorFile:
    visitors = json.load(visitorFile)

newVisitor = {
    "user": "anonvisitor",
    "timestamp": int(time.time())
}


if isinstance(visitors, list):
    visitors.append(newVisitor)
else:
    print(f"Error: JSON file is not an array")
    exit(1)

with open(visitorFilePath, 'w') as visitorFile:
    json.dump(visitors, visitorFile, indent=4)

print(f"Thanks for watering my plant")
print(f"=>	myplant.py	🪴Back To My Plant")
print(f"=>	index.gmi	🏠back to my capsule")

botanyscript = 'callbotany.py'
process = subprocess.Popen(['python', botanyscript],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)

Script to call Botany

import subprocess
import time

def run_target_script():
    try:
        process = subprocess.Popen(
            ['screen', '-dmS', 'botany_session', 'python', '/srv/botany/botany.py'],
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
        return process
    except Exception as e:
        print(f"Error starting target script: {e}")
        return None

def send_keystrokes(process):
    if process is None or process.stdin is None:
        print("Invalid process. Exiting send_keystrokes.")
        return

    keys_to_send = ['6']  # List of keys to send

    for key in keys_to_send:
        try:
            time.sleep(1)  # Wait a second between keystrokes
            process.stdin.write(key + '\n')  # Send key to the target script
            process.stdin.flush()
        except BrokenPipeError:
            print(f"BrokenPipeError: failed to send {key}")
            break
        except Exception as e:
            print(f"Error sending key {key}: {e}")
            break

def main():
    process = run_target_script()
    if process is None:
        print("Failed to start the target script. Exiting.")
        return

    time.sleep(1)  # Give the target script some time to start

    send_keystrokes(process)
    
    time.sleep(1)  # Wait a bit to let the target script process the last input

    try:
        process.kill()
        process.wait()
    except Exception as e:
        print(f"Error killing the process: {e}")

    if process.stderr:
        err_output = process.stderr.read()
        if err_output:
            print(f"Error output from target script: {err_output}")

if __name__ == "__main__":
    main()

__________________________________________________________

🏠 return to home