Skip to content
This repository was archived by the owner on Apr 11, 2024. It is now read-only.

Commit d551ac4

Browse files
committed
pretalx import
1 parent 1927cc7 commit d551ac4

File tree

8 files changed

+231
-0
lines changed

8 files changed

+231
-0
lines changed

data/events/devcon-test.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"edition": 42,
3+
"title": "Devcon Test Event",
4+
"description": "Lorem ipsum dolor sit amet..",
5+
"location": "Bangkok, Thailand",
6+
"startDate": "2024-11-01T00:00:00.000Z",
7+
"endDate": "2024-11-30T00:00:00.000Z",
8+
"venue_name": "QSNCC",
9+
"venue_description": "Queen Sirikit National Convention Center in Bangkok, Thailand",
10+
"venue_address": "60 Ratchadaphisek Rd, Khlong Toei, Bangkok 10110, Thailand",
11+
"venue_website": "https://www.qsncc.com/",
12+
"venue_directions": "https://goo.gl/maps/XLGaN7B9zViAe3DB6",
13+
"rooms": []
14+
}

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"scripts": {
1313
"build": "tsc",
1414
"start": "NODE_PATH=./dist node ./dist/index",
15+
"seed:pretalx": "ts-node ./src/db/seed-pretalx.ts",
1516
"dev:generate": "yarn swagger:generate && yarn db:generate && nodemon ./src/index.ts",
1617
"dev": "nodemon ./src/index.ts",
1718
"test": "NODE_ENV=test jest --detectOpenHandles --watchAll --no-cache",

src/clients/pretalx.ts

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import { defaultSlugify } from 'utils/content'
2+
import { CreateBlockie } from 'utils/account'
3+
import { PRETALX_CONFIG } from 'utils/config'
4+
import dayjs from 'dayjs'
5+
import utc from 'dayjs/plugin/utc'
6+
7+
dayjs.extend(utc)
8+
9+
const cache = new Map()
10+
11+
export async function GetRooms() {
12+
const rooms = await exhaustResource(`/events/${PRETALX_CONFIG.PRETALX_EVENT_NAME}/rooms`)
13+
return rooms.map((i: any) => {
14+
return {
15+
id: `${PRETALX_CONFIG.PRETALX_EVENT_NAME}_${i.name?.en ? defaultSlugify(i.name?.en) : String(i.id)}`,
16+
name: i.name?.en ?? '',
17+
description: i.description?.en ?? '',
18+
info: i.speaker_info?.en ?? '',
19+
capacity: i.capacity,
20+
}
21+
})
22+
}
23+
24+
export async function GetSpeakers() {
25+
const speakersData = await exhaustResource(`/events/${PRETALX_CONFIG.PRETALX_EVENT_NAME}/speakers`)
26+
const speakers = speakersData.map((i: any) => {
27+
const twitter = i.answers?.find((i: any) => i.question.id === PRETALX_CONFIG.PRETALX_QUESTIONS_TWITTER)?.answer
28+
const github = i.answers?.find((i: any) => i.question.id === PRETALX_CONFIG.PRETALX_QUESTIONS_GITHUB)?.answer
29+
30+
let speaker: any = {
31+
id: defaultSlugify(i.name),
32+
sourceId: i.code,
33+
name: i.name,
34+
avatar: i.avatar ?? CreateBlockie(i.name),
35+
description: i.biography ?? '',
36+
}
37+
38+
if (twitter) speaker.twitter = twitter
39+
if (github) speaker.github = github
40+
41+
return speaker
42+
})
43+
44+
return speakers
45+
}
46+
47+
export async function GetSessions() {
48+
const talks = await exhaustResource(`/events/${PRETALX_CONFIG.PRETALX_EVENT_NAME}/talks`)
49+
50+
const sessions = talks.map((i: any) => {
51+
const expertise = i.answers?.find((i: any) => i.question.id === PRETALX_CONFIG.PRETALX_QUESTIONS_EXPERTISE)?.answer as string
52+
const tagsAnswer = i.answers?.find((i: any) => i.question.id === PRETALX_CONFIG.PRETALX_QUESTIONS_TAGS)?.answer as string
53+
54+
return {
55+
id: `${PRETALX_CONFIG.PRETALX_EVENT_NAME}_${defaultSlugify(i.title)}`,
56+
sourceId: i.code,
57+
title: i.title,
58+
description: i.description ?? i.abstract,
59+
track: i.track?.en ?? '',
60+
type: i.submission_type?.en ?? '',
61+
expertise: expertise ?? '',
62+
tags: tagsAnswer
63+
? tagsAnswer.includes(',')
64+
? tagsAnswer.split(',').map((i) => i.replace(/['"]+/g, '').trim())
65+
: tagsAnswer.split(' ').map((i) => i.replace(/['"]+/g, '').trim())
66+
: [],
67+
language: 'en',
68+
speakers: i.speakers.map((i: any) => i.code),
69+
slot_start: dayjs.utc(i.slot.start).toDate(),
70+
slot_end: dayjs.utc(i.slot.end).toDate(),
71+
slot_roomId: i.slot?.room ? `${PRETALX_CONFIG.PRETALX_EVENT_NAME}_${defaultSlugify(i.slot.room.en)}` : null,
72+
}
73+
})
74+
75+
return sessions
76+
}
77+
78+
async function exhaustResource(slug: string, limit = PRETALX_CONFIG.DEFAULT_LIMIT, offset = 0, results = [] as any): Promise<any> {
79+
return get(`${slug}${slug.includes('?') ? '&' : '?'}limit=${limit}&offset=${offset}`).then((data: any) => {
80+
results.push(data.results)
81+
if (data.next) {
82+
console.log('GET', slug, 'TOTAL COUNT', data.count)
83+
return exhaustResource(slug, limit, offset + limit, results)
84+
} else {
85+
console.log('Return results', slug, results.flat().length)
86+
return results.flat()
87+
}
88+
})
89+
}
90+
91+
async function get(slug: string) {
92+
if (cache.has(slug)) {
93+
return cache.get(slug)
94+
}
95+
96+
const response = await fetch(`${PRETALX_CONFIG.PRETALX_BASE_URI}${slug}`, {
97+
headers: {
98+
Authorization: `Token ${PRETALX_CONFIG.PRETALX_API_KEY}`,
99+
},
100+
})
101+
102+
const data = await response.json()
103+
cache.set(slug, data)
104+
return data
105+
}

src/db/devcon.db

-18.3 MB
Binary file not shown.

src/db/seed-pretalx.ts

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { PrismaClient } from '@prisma/client'
2+
import { GetRooms, GetSessions, GetSpeakers } from 'clients/pretalx'
3+
import { PRETALX_CONFIG } from 'utils/config'
4+
5+
const client = new PrismaClient()
6+
7+
async function main() {
8+
console.log('Seeding Pretalx Event Schedule into Sqlite..')
9+
10+
// Rooms
11+
console.log('Importing Rooms..')
12+
const rooms = await GetRooms()
13+
for (const item of rooms) {
14+
await client.room.upsert({
15+
where: { id: item.id },
16+
update: item,
17+
create: item,
18+
})
19+
}
20+
console.log('Rooms imported', rooms.length)
21+
22+
// Update Event
23+
console.log('Update Event with Rooms..')
24+
const event = await client.event.findFirst({ where: { id: PRETALX_CONFIG.PRETALX_EVENT_NAME } })
25+
if (event) {
26+
await client.event.update({
27+
where: { id: PRETALX_CONFIG.PRETALX_EVENT_NAME },
28+
data: {
29+
rooms: {
30+
connect: rooms.map((i: any) => ({ id: i.id })),
31+
},
32+
},
33+
})
34+
35+
console.log('Rooms added to event', PRETALX_CONFIG.PRETALX_EVENT_NAME)
36+
}
37+
38+
// Speakers
39+
console.log('Importing Speakers..')
40+
const speakers = await GetSpeakers()
41+
for (const item of speakers) {
42+
await client.speaker.upsert({
43+
where: { id: item.id },
44+
update: item,
45+
create: item,
46+
})
47+
}
48+
console.log('Speakers imported', speakers.length)
49+
50+
// Sessions
51+
const sessions = await GetSessions()
52+
for (const item of sessions) {
53+
const slot_roomId = item.slot_roomId
54+
delete item.slot_roomId
55+
56+
const sessionSpeakers = speakers.filter((i: any) => item.speakers.includes(i.sourceId))
57+
let data: any = {
58+
...item,
59+
tags: item.tags.join(','),
60+
event: {
61+
connect: { id: PRETALX_CONFIG.PRETALX_EVENT_NAME },
62+
},
63+
speakers: {
64+
connect: sessionSpeakers.map((i: any) => ({ id: i.id })),
65+
},
66+
}
67+
68+
if (slot_roomId) {
69+
data.slot_room = {
70+
connect: { id: slot_roomId },
71+
}
72+
}
73+
74+
await client.session.upsert({
75+
where: { id: item.id },
76+
update: data,
77+
create: data,
78+
})
79+
}
80+
console.log('Sessions imported', sessions.length)
81+
}
82+
83+
main()
84+
.then(async () => {
85+
console.log('All done!')
86+
})
87+
.catch(async (e) => {
88+
console.error(e)
89+
process.exit(1)
90+
})

src/db/seed.ts

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import dayjs from 'dayjs'
55
const client = new PrismaClient()
66

77
async function main() {
8+
console.log('Seed local data sources into Sqlite..')
9+
810
// Rooms
911
const rooms = GetData('rooms')
1012
console.log(`- Add ${rooms.length} rooms`)

src/utils/config.ts

+14
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,20 @@ export const SERVER_CONFIG = {
4444
SMTP_PASSWORD: process.env.SMTP_PASSWORD,
4545
}
4646

47+
export const PRETALX_CONFIG = {
48+
PRETALX_API_KEY: process.env.PRETALX_API_KEY,
49+
50+
PRETALX_BASE_URI: 'https://speak.devcon.org/api', // 'https://speak.devcon.org/api' // https://speak.ticketh.xyz/api
51+
PRETALX_EVENT_NAME: 'devcon-test', // 'devcon-vi-2022' // 'pwa-data'
52+
53+
PRETALX_QUESTIONS_TWITTER: 44,
54+
PRETALX_QUESTIONS_GITHUB: 43,
55+
PRETALX_QUESTIONS_EXPERTISE: 40,
56+
PRETALX_QUESTIONS_TAGS: 42,
57+
58+
DEFAULT_LIMIT: 100,
59+
}
60+
4761
export const SESSION_CONFIG = {
4862
cookieName: API_INFO.title,
4963
password: process.env.SESSION_SECRET || 'default-test-session-secret-for-iron-session',

src/utils/content.ts

+5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import createMD from 'markdown-it'
2+
import slugify from 'slugify'
23
const md = createMD({ html: true })
34

45
export function toHtml(markdown: string, slice?: number) {
@@ -9,3 +10,7 @@ export function toHtml(markdown: string, slice?: number) {
910

1011
return md.render(markdown)
1112
}
13+
14+
export function defaultSlugify(text: string): string {
15+
return slugify(text, { lower: true, strict: true, trim: true })
16+
}

0 commit comments

Comments
 (0)