Last active
February 6, 2025 01:00
-
-
Save brianglass/fcc53b5948e0dcbef2b4598964cfeb4e to your computer and use it in GitHub Desktop.
Fetch Liturgical Information from Antiochian.org
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import sys | |
from datetime import date, datetime, timedelta | |
from urllib.parse import urljoin | |
import requests | |
HOST = 'www.antiochian.org' | |
CLIENT_ID = 'antiochian_api' | |
CLIENT_SECRET = 'TAxhx@9tH(l^MgQ9FWE8}T@NWUT9U)' | |
class Antiochian(requests.Session): | |
base_url = 'https://antiochian.org/' | |
token_endpoint = urljoin(base_url, '/connect/token') | |
liturgical_endpoint = urljoin(base_url, '/api/antiochian/LiturgicalDay/{}') | |
id_anchor = None | |
days = {} | |
def __init__(self, *args, **kwargs): | |
super().__init__(*args, **kwargs) | |
self.headers['Host'] = HOST | |
def authenticate(self): | |
response = session.post(self.token_endpoint, data={ | |
'client_id': CLIENT_ID, | |
'client_secret': CLIENT_SECRET, | |
'grant_type': 'client_credentials', | |
}) | |
response.raise_for_status() | |
token_data = response.json() | |
self.headers['Authorization'] = f'Bearer {token_data["access_token"]}' | |
# populate self.id_anchor | |
self.get_liturgical_day() | |
def get_id_from_date(self, dt): | |
anchor_dt, anchor_id = self.id_anchor | |
span = dt - anchor_dt | |
return span.days + anchor_id | |
def get_liturgical_day(self, dt=None): | |
if dt in self.days: | |
# Fetch from cache | |
return self.days[dt] | |
day_id = self.get_id_from_date(dt) if dt else 0 | |
url = self.liturgical_endpoint.format(day_id) | |
response = self.get(url) | |
if not response.ok: | |
return None | |
response_data = response.json() | |
day = response_data['liturgicalDay'] | |
if not self.id_anchor: | |
dt = datetime.strptime(day['originalCalendarDate'], '%Y-%m-%d') | |
self.id_anchor = dt.date(), day['itemId'] | |
# cache | |
self.days[dt] = day | |
return day | |
if __name__ == '__main__': | |
session = Antiochian() | |
session.authenticate() | |
for i in range(10): | |
dt = date.today() + timedelta(days=i) | |
day = session.get_liturgical_day(dt) | |
print( | |
f'{dt}: {day["feastDayTitle"].title()}\n' | |
f'\t{day["fastDesignation"].title()}\n' | |
) | |
# The api always returns 3 readings, but not all are used | |
for num in range(1, 4): | |
reading_title = day[f'reading{num}Title'] | |
if reading_title: | |
print(f'\t{reading_title.title()}') | |
print() |
Retrieve liturgical texts for the current date, in TypeScript
import axios, { AxiosInstance } from 'axios';
const HOST = 'www.antiochian.org';
const CLIENT_ID = 'antiochian_api';
const CLIENT_SECRET = 'TAxhx@9tH(l^MgQ9FWE8}T@NWUT9U)';
interface LiturgicalText {
publicUrl: string;
typeOfService: string;
}
class Antiochian {
private baseUrl = 'https://antiochian.org/';
private tokenEndpoint = `${this.baseUrl}connect/token`;
private liturgicalTextEndpoint = (date: string) => `${this.baseUrl}api/antiochian/LiturgicalTexts/${date}`;
private axiosInstance: AxiosInstance;
private texts: Record<string, LiturgicalText[]> = {};
constructor() {
this.axiosInstance = axios.create({
headers: { 'Host': HOST }
});
}
async authenticate(): Promise<void> {
const response = await this.axiosInstance.post(this.tokenEndpoint, new URLSearchParams({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
grant_type: 'client_credentials',
}).toString(), {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
const tokenData = response.data;
this.axiosInstance.defaults.headers['Authorization'] = `Bearer ${tokenData.access_token}`;
}
async getLiturgicalText(date: Date): Promise<LiturgicalText[] | null> {
const key = date.toISOString().split('T')[0]; // Format the date as YYYY-MM-DD
if (this.texts[key]) return this.texts[key];
const response = await this.axiosInstance.get(this.liturgicalTextEndpoint(key));
if (response.status !== 200) return null;
const texts: LiturgicalText[] = response.data;
this.texts[key] = texts; // Cache result
return texts;
}
}
(async () => {
const session = new Antiochian();
await session.authenticate();
// Get today's date
const dt = new Date();
const texts = await session.getLiturgicalText(dt);
if (!texts) {
console.log('No liturgical texts found for today.');
return;
}
console.log(`${dt.toDateString()}:`);
texts.forEach((text) => {
console.log(`\tType of Service: ${text.typeOfService}`);
console.log(`\tPublic URL: ${text.publicUrl}`);
});
console.log();
})();
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Converted to TypeScript