I'm auto posting hourly weather updates to Mastodon and Bluesky with some PHP, because, why not :)

After some additions to check that the data isn’t too old this is the first proper post to my ‘weather conditions’ account…

I just need to add the cron job now and it’s online.

2 Likes

Cron job is working so tomorrow I’ll be making the script(s) to post a WxSim forecast image 4 times a day.

It looks good. One thing I run into is the Bluesky 300-character limit. The error message you get back, at least to me, is confusing. It references a “rate limit exceeded,” not a character limit. It took me a bit to realize that.

Guy

I’ve improved the post by putting a link on each value that points to the relevant chart on my website. So if you want to see more about the temperature just click on the temperature value link. See the current example at this link…

BSky weather conditions post including links

I’ve linked the entire line for now, but I’m wondering whether to just link the name string or the value.

Yes please for the BlueSky script.

Which one? The original @beun.net PHP one, or the @grwkak modified PHP version or I’ve posted a Python one further up the thread.

I’ve now added tags to the Python script. The script is now quite speciifc to my requirements, but if anyone wants to use Python I’m happy to post it with some comments describing how you’d need to change it for your own purposes.

I’ve got image uploading working now. I still need to do some tidying up but I’m getting close to having what I set out to make.

The original @beun.net PHP one

I’ve sent you the ZIP file.

1 Like

Including those links is really nice. But I would indeed go for the option of only placing a link on the value itself to make it clearer it’s clickable and why.

Other than that I am impressed by your Python code (and how little seems to be needed).

1 Like

I think I’ve finished with this posting script, at least until someone suggests an improvement!

Latest changes are:

  1. The conditions links are now just on the values
  2. Checks if the conditions data is recent and doesn’t post if not
  3. Checks if the forecast graphic is recent and only posts conditions if it’s not
  4. Alt text added to the image. The alt text contains a text version of the forecast
  5. Changed the ‘More conditions’ link format and added ‘More forecast’

I have WxSim running every hour and the image is generated on the hour using the latest WxSim data. The BSky post is made a minute after the image generation runs.

The snip below is from this post

ok… this is looking good now, could someone send me the files needed for this please??

It’s not easy to do that, partly because I didn’t set out with the intention of making it general purpose for anyone to use. It comprises a number of components:

  1. Something to create and upload a textfile containing the conditions text you want to post. This will depend on what software you’re using, e.g. with WD you’d use a custom file containing tags, etc. This is standard stuff so I wouldn’t propose documenting it.
  2. WxSim running to produce and upload plaintext.txt to a schedule. This is also standard stuff so I wouldn’t propose documenting it.
  3. A script to convert the WxSim plaintext data into a JPG image. This is where it gets difficult. My process uses heavily modified versions of a number of Leuven WxSim scripts. I don’t know if these scripts are still available and as my script relies on other parts of that script system it’s not much use without the other scripts. The modified scripts also use the particular config of my webserver, i.e. version of PHP and ImageMagick installation. I don’t propose uploading this part of the process. It would be too difficult for me to provide support for it the way it is. I could envisage a v2 of the image production script that was standalone (although still having specific PHP/module requirements) but that’s not currently on my radar.
  4. A Python script that grabs the forecast image, a JSON status file, an Alt-text file and the conditions text, formats these into a BSky post and posts it.

I will upload a version of the Python posting script with comments. I’ll leave the image processing bits in so that people can see how to use them, but if you want to post a forecast image then for now you’d need to do that bit for yourself and modify the Python to support your own method.

Here’s my latest Python script with some notes:

  1. On the “#!” line include the path to python3 on your system. Mine just points at a test virtual environment
  2. You’ll need to install the atproto module first - “pip3 install atproto” or whatever you need for your Python install (possibly apt install).
  3. You may need to install additional Python modules. See the list in the script.
  4. If you’re using your own PDS (unlikely) then change “Client()” to “Client()”. If this doesn’t mean anything then you are almost certainly using the default BSky PDS and can continue without changes.
  5. ‘bluesky_handle’ is your handle (without the ‘@’).
  6. ‘bluesky_password’ is your password. I’d recommend creating an application password rather than using your main password.
  7. Set target_url to the URL of the text file you want to put in the post.
  8. The script expects to find the date and time the text file was produced in the first line in the format “YYYY-MM-DD HH:MM:SS”. There can be other text on the line too as long as the date/time is correctly formatted. If your file has a different date/time format you’ll need to change the lines following “if i == 1:”. You may also want to change the maximum data age (1000 seconds for me) because new conditions data is uploaded every 15 minutes.
  9. The script also expects each conditions line to have a format of “Name: condition value”. If you’re using a different format you’ll need to modify the section following “if text.find(”: “) > -1:” to suit your format. If you want less or more conditions you’ll aso need to modify the script accordingly by adding/removing lines. You need to provide a URL for each condition which will be a link from the condition value.
  10. You’ll need to add in URLs for your own web pages to the links for ‘More conditions’ and ‘More forecast’
  11. You’ll need to modify the pt.tag() lines to suit any tags you want to use on the page.
  12. Most of the script below “# Check if there’s a recent forecast image to upload” is checking if the forecast image is new enough and handling embedding the forecast image/alt-text. You would need to modify this extensively to suit your own method of producing the forecast image. If you don’t want to upload an image, comment this section out or delete it, just leaving “post = client.send_post(pt)” line (with a suitable indent).
#!/root/bsky/bin/python3

from atproto import Client,client_utils
from urllib.request import urlopen
import datefinder
from datetime import datetime
import sys
import json
from pathlib import Path

def main():
    client = Client()
    profile = client.login('bluesky_handle', 'bluesky_password')

    target_url = "URL to text file"
    curr_dt = datetime.now()

    pt = client_utils.TextBuilder()
    i = 1
    for line in urlopen(target_url):
        text = line.decode("utf-8")
        if i == 1:
            date_matches = datefinder.find_dates(text)
            for date_match in date_matches:
                data_dt = datetime.strptime(str(date_match),"%Y-%m-%d %H:%M:%S")
                data_age = curr_dt.timestamp() - data_dt.timestamp()
                if data_age > 1000:
                    print("Not updating. Data too old - ",text)
                    sys.exit()
        if text.find(": ") > -1:
            parts = text.split(": ")
            pt.text(parts[0]+": ")
            if "Temperature:" in text:
                pt.link(parts[1],'URL to your temperature web page')
            elif "Rain Today:" in text:
                pt.link(parts[1],'URL to your rain web page')
            elif "Wind:" in text:
                pt.link(parts[1],'URL to your wind web page')
            elif "Max Gust:" in text:
                pt.link(parts[1],'URL to your gusts web page (maybe just repeat wind)')
            elif "Humidity:" in text:
                pt.link(parts[1],'URL to your humidity web page')
            elif "Sun:" in text:
                pt.link(parts[1],'URL to your solar web page')
            elif "UV:" in text:
                pt.link(parts[1],'URL to your UV web page (maybe just repeat wind)')
            elif "Pressure:" in text:
                pt.link(parts[1],'URL to your pressure web page')
        else:
            pt.text(text)
        i += 1

    pt.text('\nMore ')
    pt.link('conditions','URL of your weather web site')
    pt.text(' More ')
    pt.link('forecast\n','URL of your forecast web site')

    pt.tag('#Blackpool ','blackpool')
    pt.tag('#Weather','weather')

    # Check if there's a recent forecast image to upload

    with open('location of the forecast status JSON file on your server') as j:
        image_data = json.load(j)

    if curr_dt.timestamp() - image_data['image']['imageTime'] < 3600:

        # Upload forecast image file
        with open('location of the image JPEG file on your server', 'rb') as f:
            img_data = f.read()

        # Read alt text from file
        alt_text = Path('location of the image alt-text file on your server').read_text()

        client.send_image(text=pt, image=img_data, image_alt=alt_text)
    else:
        post = client.send_post(pt)

if __name__ == '__main__':
    main()

To use:

  1. Create a post.py file containing the code above.
  2. Edit the bits you need to change.
  3. Run the script from a cron job.

Now that I’ve got the difficult script done I can move on to some others, e.g.

  • Daily summary
  • Monthly summary
  • Annual summary
  • New records - although I don’t expect this to trigger very often

Just being text based makes these pretty easy to do.

1 Like

Hi, I’m also interested in the PHP code to get posting to Bluesky if you’re able to share please :slight_smile:

(Mastodon would be a bonus too if you can share both!)

(sidenote, have you thought about sharing the code on GitHub or even just as a gist on GitHub if it’s just a PHP file or few, to save people asking!)

@beun.net, @grwkak, your scpits work great!
Thank you.
Have you found a way to post the text with an image?

I couldn’t find any information or examples of how to use the PHP/cURL interface to upload and embed an image in a post. That’s why I swapped to using Python.

1 Like

@beun.net is the main author - I changed a few words!

Guy