diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7b0670e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +log.txt \ No newline at end of file diff --git a/README.md b/README.md index 2e122ad..a3836e7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Discord cardiParty webhook +# Discord cardiCast webhook -This is a simple webhook to push new cardiParties into the cardiParty channel. +This is a simple webhook to push new cardiCast episodes into the cardiCast Discord channel. ## install @@ -14,43 +14,37 @@ This is a simple webhook to push new cardiParties into the cardiParty channel. We run this on the newcardigan wordpress server. -1. With a cron job we call `get_party.sh` -2. The shell script set env values and uses the civiCRM API using `cv` to grab the details of the latest cardiParty -3. We pipe that string into `webhook.py` -4. The script checks a custom RSS feed for new parties -5. If no new party, end -6. If new party, +1. With a cron job we call `trigger.sh` +2. The shell script sets env values then calls `webhook.py` +4. The python script checks a custom RSS feed for new podcast episodes +5. If no new episode, end +6. If new episode, 1. save the guid to `latest_post.txt` for the next round of checking - 2. use the image and title from the RSS feed and the details from the cv API call + 2. use the values from the RSS feed 3. publish via a webhook to Discord ## env values -These are all set in `get_party.sh`, not in crontab. Because we need most of them in a subsequent call (either inside `cv` or in `webhook.py`) we `export` them all. +These are all set in `trigger.sh`, not in crontab, to keep things contained. We need to include some secrets via environment values: -**channel** is the channel ID (`DISCORD_CHANNEL`) -**token** is the secret token for the webhook (`DISCORD_TOKEN`) -**cardiparty_ping** is the ID of the `@cardiParty ping` role (`DISCORD_CARDIPARTY_PING`) +* the guild/server ID (`DISCORD_GUILD`) +* the secret token for the webhook (`DISCORD_TOKEN`) +* the ID of the `@cardiCast ping` role (`DISCORD_CARDICAST_PING`) + +And because we run python in a virtual environment: -There are also a couple of other things we need to do: -**civicrm_settings** - set `CIVICRM_SETTINGS` so that `cv` can find it **venv** - we need to activate the venv using `source ` ## Cron job command ```sh -*/15 * * * * cd /home/cardigan/rss-discord-bot && ./get_party.sh -``` -`get_party.sh` should pipe a string like this into `webhook.py`: - -``` -[{"id":108,"title":"Melbourne Art Library","address.city":"Melbourne","start_date":"2024-04-06 16:30:00","summary":"Melbourne Art Library (MAL) is a not-for-profit lending library that collects specialised art and design texts. They are proudly independent and are curious about what being a 'library' means."}] +*/18 * * * * cd /home/cardigan/rss-discord-bot && ./trigger.sh ``` ## RSS feed -The rss feed is `https://newcardigan.org/category/cardiparties/?feed=cardipartyfeed`. +The rss feed is `https://newcardigan.org/category/cardiparties/?feed=featured_image_feed`. -This special `cardipartyfeed` is a slightly modified RSS2 feed. The only thing it does differently is filter out everything that isn't a cardiparty ,and include the featured image in an `enclosure` so that we can pick it up directly from the feed. See the newcardigan WordPress theme for how this works. \ No newline at end of file +This special `featured_image_feed` is a slightly modified RSS2 feed. The only thing it does differently is include the featured image in an `enclosure` so that we can pick it up directly from the feed. See the newcardigan WordPress theme for how this works. \ No newline at end of file diff --git a/get_party.sh b/get_party.sh deleted file mode 100755 index 7fda6c0..0000000 --- a/get_party.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -# set envs and paths -export PATH=/home/cardigan/rss-discord-bot/venv/bin:usr/local/bin:usr/bin: -source /home/cardigan/rss-discord-bot/venv/bin/activate -export CIVICRM_SETTINGS="/var/www/html/wp-content/uploads/civicrm/civicrm.settings.php" -export DISCORD_SERVER="" -export DISCORD_TOKEN="" -export DISCORD_CARDIPARTY_PING="" - -cv api4 Event.get '{"select":["title","address.city","start_date","summary"],"join":[["Address AS address","LEFT",["loc_block_id.address_id","=","address.id"]]],"orderBy":{"start_date":"DESC"},"limit":1}' | ./webhook.py >> /home/cardigan/discord.log 2>&1 \ No newline at end of file diff --git a/latest_post.txt b/latest_post.txt new file mode 100644 index 0000000..e69de29 diff --git a/trigger.sh b/trigger.sh new file mode 100755 index 0000000..bf6f453 --- /dev/null +++ b/trigger.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# set envs and paths +export PATH=/home/cardigan/rss-discord-bot/venv/bin:usr/local/bin:usr/bin: +source /home/cardigan/rss-discord-bot/venv/bin/activate +export DISCORD_GUILD="" +export DISCORD_TOKEN="" +export DISCORD_CARDICAST_PING="" + +./webhook.py >> /home/cardigan/discord.log 2>&1 \ No newline at end of file diff --git a/webhook.py b/webhook.py index 35281fd..6a38098 100755 --- a/webhook.py +++ b/webhook.py @@ -8,54 +8,45 @@ import sys import feedparser import requests -dc_server = os.getenv("DISCORD_SERVER") # this is actually the instance, not a channel +guild = os.getenv("DISCORD_GUILD") # Discord server code token = os.getenv("DISCORD_TOKEN") # token for this bot -cardiparty_ping = os.getenv("DISCORD_CARDIPARTY_PING") +cardicast_ping = os.getenv("DISCORD_CARDICAST_PING") # Discord role -# get the latest cardiparty with image as enclosure -f = feedparser.parse("https://newcardigan.org/category/cardiparties/?feed=cardipartyfeed") -first = f.entries[0] +# get the latest post with image as enclosure +f = feedparser.parse("https://newcardigan.org/category/cardicast/?feed=featured_image_feed") +p = f.entries[0] # check whether we have already seen this entry with open("latest_post.txt", "r+") as f: guid = f.read().strip() f.close() -if guid != first.guid: +if guid != p.guid: # update the guid with open("latest_post.txt", "w+") as f: - f.write(first.guid) + f.write(p.guid) f.close() - api_response = sys.stdin.read() # read the API call output that was piped in - api_data = json.loads(api_response)[0] + content = f"[<:newCardigan:1280097925149626419> **{p.title}**]({p.link})\n\n{p.description}\n\n<@&{cardicast_ping}>\n\n" + embeds = [ + { + "title": "Listen to this episode right now", + "url": p.enclosures[1].href, + "color": 16741516, + "image": { + "url": p.enclosures[0].href + } + } + ] - title = api_data["title"] - city = api_data["address.city"] - start_date = api_data["start_date"] - summary = api_data["summary"] - start_date = datetime.fromisoformat(start_date).astimezone().strftime( - "%I:%M%p %a %d %b %Y" - ).strip("0") # remove time zero padding if any - - content = f"[<:newCardigan:1280097925149626419> **{title}**]({first.link})\n_{city}_\n_{start_date}_\n\n{summary}\n\n<@&{cardiparty_ping}>" - embeds = [{ - "title": "Find out more and register!", - "url": first.link, - "color": 16741516, - "image": { - "url": first.enclosures[0].href - } - }] - - headers = {'user-agent': 'cardiParty-discord-bot/1.0.0'} - url = f"https://discord.com/api/webhooks/{dc_server}/{token}" + headers = {'user-agent': 'cardiCast-discord-bot/1.0.0'} + url = f"https://discord.com/api/webhooks/{guild}/{token}" payload = { - "thread_name": f"{first.title} | {title}", + "thread_name": f"{p.title}", "content": content, "embeds": embeds, - "allowed_mentions": { "roles": [cardiparty_ping] } + "allowed_mentions": { "roles": [cardicast_ping] } } r = requests.post(url, json=payload, headers=headers) - print(r) - r.raise_for_status() # if we got a 4xx response this will log it + print(datetime.now().isoformat(' '), r) + r.raise_for_status() # if we got a 4xx response \ No newline at end of file