adjust for cardicast

This commit is contained in:
Hugh Rundle 2024-09-16 10:23:55 +10:00
parent ed6f7d7ca8
commit 92c1524acf
Signed by: hugh
GPG key ID: A7E35779918253F9
6 changed files with 53 additions and 67 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
.env
log.txt

View file

@ -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 <path/to/venv>`
## 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.
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.

View file

@ -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="<server_id>"
export DISCORD_TOKEN="<token>"
export DISCORD_CARDIPARTY_PING="<group_id>"
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

0
latest_post.txt Normal file
View file

10
trigger.sh Executable file
View file

@ -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

View file

@ -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