adjust for cardicast
This commit is contained in:
parent
ed6f7d7ca8
commit
92c1524acf
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.env
|
||||||
|
log.txt
|
40
README.md
40
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
|
## 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.
|
We run this on the newcardigan wordpress server.
|
||||||
|
|
||||||
1. With a cron job we call `get_party.sh`
|
1. With a cron job we call `trigger.sh`
|
||||||
2. The shell script set env values and uses the civiCRM API using `cv` to grab the details of the latest cardiParty
|
2. The shell script sets env values then calls `webhook.py`
|
||||||
3. We pipe that string into `webhook.py`
|
4. The python script checks a custom RSS feed for new podcast episodes
|
||||||
4. The script checks a custom RSS feed for new parties
|
5. If no new episode, end
|
||||||
5. If no new party, end
|
6. If new episode,
|
||||||
6. If new party,
|
|
||||||
1. save the guid to `latest_post.txt` for the next round of checking
|
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
|
3. publish via a webhook to Discord
|
||||||
|
|
||||||
## env values
|
## 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:
|
We need to include some secrets via environment values:
|
||||||
|
|
||||||
**channel** is the channel ID (`DISCORD_CHANNEL`)
|
* the guild/server ID (`DISCORD_GUILD`)
|
||||||
**token** is the secret token for the webhook (`DISCORD_TOKEN`)
|
* the secret token for the webhook (`DISCORD_TOKEN`)
|
||||||
**cardiparty_ping** is the ID of the `@cardiParty ping` role (`DISCORD_CARDIPARTY_PING`)
|
* 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>`
|
**venv** - we need to activate the venv using `source <path/to/venv>`
|
||||||
|
|
||||||
## Cron job command
|
## Cron job command
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
*/15 * * * * cd /home/cardigan/rss-discord-bot && ./get_party.sh
|
*/18 * * * * cd /home/cardigan/rss-discord-bot && ./trigger.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."}]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## RSS feed
|
## 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.
|
11
get_party.sh
11
get_party.sh
|
@ -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
0
latest_post.txt
Normal file
10
trigger.sh
Executable file
10
trigger.sh
Executable 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
|
51
webhook.py
51
webhook.py
|
@ -8,54 +8,45 @@ import sys
|
||||||
import feedparser
|
import feedparser
|
||||||
import requests
|
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
|
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
|
# get the latest post with image as enclosure
|
||||||
f = feedparser.parse("https://newcardigan.org/category/cardiparties/?feed=cardipartyfeed")
|
f = feedparser.parse("https://newcardigan.org/category/cardicast/?feed=featured_image_feed")
|
||||||
first = f.entries[0]
|
p = f.entries[0]
|
||||||
# check whether we have already seen this entry
|
# check whether we have already seen this entry
|
||||||
with open("latest_post.txt", "r+") as f:
|
with open("latest_post.txt", "r+") as f:
|
||||||
guid = f.read().strip()
|
guid = f.read().strip()
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
if guid != first.guid:
|
if guid != p.guid:
|
||||||
# update the guid
|
# update the guid
|
||||||
with open("latest_post.txt", "w+") as f:
|
with open("latest_post.txt", "w+") as f:
|
||||||
f.write(first.guid)
|
f.write(p.guid)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
api_response = sys.stdin.read() # read the API call output that was piped in
|
content = f"[<:newCardigan:1280097925149626419> **{p.title}**]({p.link})\n\n{p.description}\n\n<@&{cardicast_ping}>\n\n"
|
||||||
api_data = json.loads(api_response)[0]
|
embeds = [
|
||||||
|
{
|
||||||
title = api_data["title"]
|
"title": "Listen to this episode right now",
|
||||||
city = api_data["address.city"]
|
"url": p.enclosures[1].href,
|
||||||
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,
|
"color": 16741516,
|
||||||
"image": {
|
"image": {
|
||||||
"url": first.enclosures[0].href
|
"url": p.enclosures[0].href
|
||||||
}
|
}
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
|
|
||||||
headers = {'user-agent': 'cardiParty-discord-bot/1.0.0'}
|
headers = {'user-agent': 'cardiCast-discord-bot/1.0.0'}
|
||||||
url = f"https://discord.com/api/webhooks/{dc_server}/{token}"
|
url = f"https://discord.com/api/webhooks/{guild}/{token}"
|
||||||
payload = {
|
payload = {
|
||||||
"thread_name": f"{first.title} | {title}",
|
"thread_name": f"{p.title}",
|
||||||
"content": content,
|
"content": content,
|
||||||
"embeds": embeds,
|
"embeds": embeds,
|
||||||
"allowed_mentions": { "roles": [cardiparty_ping] }
|
"allowed_mentions": { "roles": [cardicast_ping] }
|
||||||
}
|
}
|
||||||
|
|
||||||
r = requests.post(url, json=payload, headers=headers)
|
r = requests.post(url, json=payload, headers=headers)
|
||||||
print(r)
|
print(datetime.now().isoformat(' '), r)
|
||||||
r.raise_for_status() # if we got a 4xx response this will log it
|
r.raise_for_status() # if we got a 4xx response
|
Loading…
Reference in a new issue