Skip to content

Commit

Permalink
feat: add bluesky
Browse files Browse the repository at this point in the history
Signed-off-by: vsoch <[email protected]>
  • Loading branch information
vsoch committed Dec 2, 2024
1 parent a5d54f6 commit fc9d3a3
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 46 deletions.
1 change: 0 additions & 1 deletion .github/workflows/post-jobs-slack.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ jobs:
deploy: false
test: true


- id: multifield_updater
name: Job Updater
uses: ./
Expand Down
50 changes: 35 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The jobs updater is a simple GitHub action application to, given some trigger
and a yaml file with a list of jobs (or other links):

```
```console
- name: My Job
...
url: https://my-job.org/12345
Expand Down Expand Up @@ -80,7 +80,7 @@ jobs:
```
In the above, we will include the url and name fields, and use the url field to determine uniqueness (default).
Given that you have the slack webhook as a secret provided to the action and `deploy_slack` is true, the default `deploy`
Given that you have the slack webhook as a secret provided to the action and `slack_deploy` is true, the default `deploy`
variable (to indicate all services) is true and deployment will happen. If you just want to test, then do:

```yaml
Expand Down Expand Up @@ -113,11 +113,9 @@ aren't necessarily new) then add test:

If test is true, deploy will always be set to false.

### Deploy to Twitter
### Deploy to BlueSky

To deploy to Twitter (in addiction to slack) you are required to set `deploy_twitter`
to true, and also define all the needed environment variables in your repository
secrets.
To deploy to BlueSky, you should set `bluesky_deploy` to true, and also define all the needed environment variables in your repository secrets.

```yaml
...
Expand All @@ -127,15 +125,10 @@ secrets.
with:
filename: "_data/jobs.yaml"
keys: "url,name"
test: false
slack_deploy: true
# Also deploy to Twitter (all secrets required in repository secrets)
twitter_deploy: true
twitter_api_secret: ${{ secrets.TWITTER_ACCESS_SECRET }}
twitter_api_key: ${{ secrets.TWITTER_ACCESS_TOKEN }}
twitter_consumer_secret: ${{ secrets.TWITTER_CONSUMER_API_SECRET }}
twitter_consumer_key: ${{ secrets.TWITTER_CONSUMER_API_KEY }}
test: false
bluesky_deploy: true
bluesky_password: ${{ secrets.BLUESKY_PASSWORD }}
bluesky_email: ${{ secrets.BLUESKY_EMAIL }}
```

### Deploy to Mastodon
Expand Down Expand Up @@ -184,6 +177,30 @@ and then set `deploy_discord` to true, along with adding the webhook to your rep
discord_webhook: ${{ secrets.DISCORD_WEBHOOK }}
```

### Deploy to Twitter

To deploy to Twitter (in addiction to slack) you are required to set `twitter_deploy`
to true, and also define all the needed environment variables in your repository
secrets.

```yaml
...
- id: updater
name: Job Updater
uses: rseng/jobs-updater@add/deploy-arg
with:
filename: "_data/jobs.yaml"
keys: "url,name"
test: false
# Deploy to Twitter (all secrets required in repository secrets)
twitter_deploy: true
twitter_api_secret: ${{ secrets.TWITTER_ACCESS_SECRET }}
twitter_api_key: ${{ secrets.TWITTER_ACCESS_TOKEN }}
twitter_consumer_secret: ${{ secrets.TWITTER_CONSUMER_API_SECRET }}
twitter_consumer_key: ${{ secrets.TWITTER_CONSUMER_API_KEY }}
```

## Variables

### Inputs
Expand All @@ -199,6 +216,9 @@ The following variables are available. You can also look at the [action.yml](act
| hashtag | A hashtag to use (defaults to `#Rseng`) | false | #RSEng |
| test | Test the updater (ensure there are jobs) | true | false |
| deploy | Global deploy across any service set to true? | true | true |
| bluesky_deploy | Deploy to BlueSky? | true | false |
| bluesky_email | BlueSky email | false | unset |
| bluesky_password | BlueSky password | false | unset |
| slack_deploy | Deploy to Slack? | true | false |
| slack_webhook | Slack webhook to deploy to. | false | unset |
| discord_deploy | Deploy to Discord? | true | false |
Expand Down
22 changes: 18 additions & 4 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: 'Jobs Updater'
description: "The jobs updater will respond on some trigger, and them parse a jobs file for changes, posting to one or more services."
description: "Respond on a trigger and parse a jobs file for changes, posting to one or more services."
inputs:
filename:
description: the filename for the jobs
Expand Down Expand Up @@ -35,6 +35,7 @@ inputs:
slack_webhook:
description: Slack webhook to deploy to.
required: false

discord_deploy:
description: Deploy to Discord?
required: true
Expand All @@ -43,8 +44,18 @@ inputs:
description: Discord webhook to deploy to.
required: false

# If you want to post to Twitter, all of these credentials are required for a specific user
# If you want to post to BlueSky, both of these are required
bluesky_deploy:
description: Boolean to deploy to BlueSky
required: false
bluesky_password:
description: BlueSky account password
required: false
bluesky_email:
description: BlueSky account email
required: false

# If you want to post to Twitter, all of these credentials are required for a specific user
# API keys are typically generated on behalf of a user (at the bottom of the interface)
twitter_deploy:
description: Deploy to Twitter?
Expand All @@ -64,7 +75,7 @@ inputs:
description: consumer secret generated for the entire app
required: false

# If you want to post to Mastodon, these values are required
# If you want to post to Mastodon, these values are required
mastodon_deploy:
description: Boolean to deploy to Mastodon
required: false
Expand All @@ -91,7 +102,7 @@ runs:
steps:
- name: Install Python Dependencies
run: |
pip install pyyaml requests Mastodon.py
pip install pyyaml requests Mastodon.py atproto
pip install git+https://github.com/tweepy/tweepy.git
shell: bash

Expand All @@ -110,6 +121,9 @@ runs:
INPUT_DEPLOY: ${{ inputs.deploy }}
SLACK_DEPLOY: ${{ inputs.slack_deploy }}
SLACK_WEBHOOK: ${{ inputs.slack_webhook }}
BLUESKY_DEPLOY: ${{ inputs.bluesky_deploy }}
BLUESKY_PASSWORD: ${{ inputs.bluesky_password }}
BLUESKY_EMAIL: ${{ inputs.bluesky_email }}
TWITTER_DEPLOY: ${{ inputs.twitter_deploy }}
TWITTER_API_KEY: ${{ inputs.twitter_api_key }}
TWITTER_API_SECRET: ${{ inputs.twitter_api_secret }}
Expand Down
10 changes: 10 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ if [[ "${INPUT_TEST}" == "true" ]]; then
DEPLOY=false
fi

DEPLOY_BLUESKY=false
if [ ! -z ${BLUESKY_EMAIL+x} ] && [ ! -z ${BLUESKY_PASSWORD+x} ] && [[ "${BLUESKY_DEPLOY}" == "true" ]]; then
DEPLOY_BLUESKY=true
fi

# If everything not unset and deploy twitter is true, we deploy!
DEPLOY_TWITTER=false
if [ ! -z ${TWITTER_API_KEY+x} ] && [ ! -z ${TWITTER_API_SECRET+x} ] && [ ! -z ${TWITTER_CONSUMER_KEY+x} ] && [ ! -z ${TWITTER_CONSUMER_SECRET+x} ] && [[ "${TWITTER_DEPLOY}" == "true" ]]; then
Expand Down Expand Up @@ -74,6 +79,7 @@ fi
# Alert the user everything that will happen
printf " Global Deploy: ${DEPLOY}\n"
printf "Deploy Mastodon: ${DEPLOY_MASTODON}\n"
printf " Deploy BlueSky: ${DEPLOY_BLUESKY}\n"
printf " Deploy Twitter: ${DEPLOY_TWITTER}\n"
printf " Deploy Discord: ${DEPLOY_DISCORD}\n"
printf " Deploy Slack: ${DEPLOY_SLACK}\n"
Expand Down Expand Up @@ -111,6 +117,10 @@ if [[ "${DEPLOY_DISCORD}" == "true" ]]; then
COMMAND="${COMMAND} --deploy-discord"
fi

if [[ "${DEPLOY_BLUESKY}" == "true" ]]; then
COMMAND="${COMMAND} --deploy-bluesky"
fi

echo "${COMMAND}"

${COMMAND}
Expand Down
108 changes: 82 additions & 26 deletions find-updates.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,48 @@
# 1. Reads in a current and changed yaml file
# 2. Finds changes between the two
# 3. Post them to slack
# 4. Optionally post them to Twitter
# 5. Optionally post them to Mastodon
# 4. Optionally post them to Twitter, Mastodon, Discord, etc.

import argparse
import requests
import random
import json
import os
import random
import sys
import yaml

import requests
import tweepy
import yaml
from atproto import Client as BlueskyClient
from atproto import TextBuilder
from mastodon import Mastodon

# Shared headers for slack / discord
headers = {"Content-type": "application/json"}
success_codes = [200, 201, 204]


icons = [
"⭐️",
"😍️",
"❤️",
"👀️",
"✨️",
"🤖️",
"😎️",
"💼️",
"🤩️",
"🥑",
"🥳",
"🎉",
"😸️",
"😻️",
"👉️",
"🕶️",
"🔥️",
"💻️",
]


def read_yaml(filename):
"""
Read yaml from file.
Expand Down Expand Up @@ -114,6 +138,14 @@ def get_parser():
help="deploy to Discord (required webhook URL in environment)",
)

update.add_argument(
"--deploy-bluesky",
dest="deploy_bluesky",
action="store_true",
default=False,
help="deploy to BlueSky (required user/pass in environment)",
)

update.add_argument(
"--deploy-mastodon",
dest="deploy_mastodon",
Expand Down Expand Up @@ -188,6 +220,20 @@ def get_twitter_client():
)


def get_bluesky_client():
"""
Get a BlueSky (atproto) client, also ensure all needed envars are provided.
"""
required = [
"BLUESKY_PASSWORD",
"BLUESKY_EMAIL",
]
client = BlueskyClient()
envars = get_required_envars(required, "bluesky")
client.login(envars["BLUESKY_EMAIL"], envars["BLUESKY_PASSWORD"])
return client


def get_mastodon_client():
"""
Get a Mastodon client, requiring a token and base URL.
Expand All @@ -203,7 +249,7 @@ def get_mastodon_client():
)


def prepare_post(entry, keys):
def prepare_post(entry, keys, without_url=False):
"""
Prepare the post.
Expand All @@ -212,6 +258,9 @@ def prepare_post(entry, keys):
post = ""
for key in keys:
if key in entry:
# For BlueSky, we include the url separately
if key == "url" and without_url:
continue
if key == "url":
post = post + entry[key] + "\n"
else:
Expand All @@ -233,6 +282,25 @@ def deploy_slack(webhook, message):
)


def deploy_bluesky(client, entry, hashtag):
"""
Deploy to bluesky. We add the job link separately.
"""
tb = TextBuilder()

# Prepare the post, but without the url
post = prepare_post(entry, keys, without_url=True)
choice = random.choice(icons)
message = f"New {hashtag} Job! {choice}\n{post}"
print(message)

# Add the text to the textbuilder
tb.text(message)
tb.link("CBOR", entry["url"])
response = client.send_post(tb)
print(f"Posted to bluesky {response.uri}: {response.cid}")


def deploy_discord(webhook, message):
"""
Deploy a post to Discord
Expand Down Expand Up @@ -284,6 +352,11 @@ def help(return_code=0):
if args.deploy_mastodon:
mastodon_client = get_mastodon_client()

# Deploying to BlueSky?
bluesky_client = None
if args.deploy_bluesky:
bluesky_client = get_bluesky_client()

# Prepare webhooks for slack and mastodon
slack_webhook = os.environ.get("SLACK_WEBHOOK")
discord_webhook = os.environ.get("DISCORD_WEBHOOK")
Expand Down Expand Up @@ -331,27 +404,7 @@ def help(return_code=0):

matrix = []

# Format into slack messages
icons = [
"⭐️",
"😍️",
"❤️",
"👀️",
"✨️",
"🤖️",
"😎️",
"💼️",
"🤩️",
"😸️",
"😻️",
"👉️",
"🕶️",
"🔥️",
"💻️",
]

for entry in new:

# Prepare the post
post = prepare_post(entry, keys)
choice = random.choice(icons)
Expand Down Expand Up @@ -379,6 +432,9 @@ def help(return_code=0):
if args.deploy_twitter and twitter_client:
deploy_twitter(twitter_client, newline_message)

if args.deploy_bluesky and bluesky_client:
deploy_bluesky(bluesky_client, entry, args.hashtag)

# If we are instructed to deploy to mastodon and have a client
if args.deploy_mastodon and mastodon_client:
mastodon_client.toot(status=message)
Expand Down

0 comments on commit fc9d3a3

Please sign in to comment.