From 3f61ce8d5230221f54d4fcd85694b678bf565a59 Mon Sep 17 00:00:00 2001 From: Keiichiro Amemiya Date: Fri, 14 Jun 2024 18:43:55 +0200 Subject: [PATCH 1/8] automate event start time --- app/routes/_base.events._index.tsx | 32 ++++++++++--------- app/routes/admin.$/resources/events.tsx | 1 - app/routes/admin.sync.tsx | 10 ++++++ migrations/0012_event-start-time-optional.sql | 19 +++++++++++ prisma/schema.prisma | 2 +- 5 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 migrations/0012_event-start-time-optional.sql diff --git a/app/routes/_base.events._index.tsx b/app/routes/_base.events._index.tsx index 890f225..06548be 100644 --- a/app/routes/_base.events._index.tsx +++ b/app/routes/_base.events._index.tsx @@ -18,7 +18,7 @@ export default () => { const eventsByYear = new Map(); for (const event of events) { - const year = new Date(event.startsAt).getFullYear(); + const year = event.startsAt ? new Date(event.startsAt).getFullYear() : -1; const existingEvents = eventsByYear.get(year); if (existingEvents) { existingEvents.push(event); @@ -32,20 +32,22 @@ export default () => { イベント一覧 - {[...eventsByYear].map(([year, events]) => ( - - - {year}年 - -
    - {events.map((event) => ( -
  • - {event.name} -
  • - ))} -
-
- ))} + {[...eventsByYear] + .sort((a, b) => b[0] - a[0]) + .map(([year, events]) => ( + + + {year === -1 ? "不明" : `${year.toFixed()}年`} + +
    + {events.map((event) => ( +
  • + {event.name} +
  • + ))} +
+
+ ))} ); }; diff --git a/app/routes/admin.$/resources/events.tsx b/app/routes/admin.$/resources/events.tsx index ab7886b..9cb2740 100644 --- a/app/routes/admin.$/resources/events.tsx +++ b/app/routes/admin.$/resources/events.tsx @@ -39,7 +39,6 @@ const EventsCreate = () => { - diff --git a/app/routes/admin.sync.tsx b/app/routes/admin.sync.tsx index 2e48513..87c6cfc 100644 --- a/app/routes/admin.sync.tsx +++ b/app/routes/admin.sync.tsx @@ -50,6 +50,12 @@ export const action = async ({ request, context }: ActionFunctionArgs) => { const runsToDelete = existingRuns.filter( (run) => !run.syncExternalId || !newRunIds.has(run.syncExternalId), ); + let startsAt: Date | undefined; + for (const run of runs) { + if (!startsAt || run.startsAt < startsAt) { + startsAt = run.startsAt; + } + } await Promise.all([ ...runsToDelete.map((run) => @@ -74,6 +80,10 @@ export const action = async ({ request, context }: ActionFunctionArgs) => { }, }), ), + context.prisma.events.update({ + where: { id: eventId }, + data: { startsAt }, + }), ]); return json(null); diff --git a/migrations/0012_event-start-time-optional.sql b/migrations/0012_event-start-time-optional.sql new file mode 100644 index 0000000..ef79c63 --- /dev/null +++ b/migrations/0012_event-start-time-optional.sql @@ -0,0 +1,19 @@ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_Events" ( + "id" TEXT NOT NULL PRIMARY KEY, + "name" TEXT NOT NULL, + "shortName" TEXT NOT NULL, + "startsAt" DATETIME, + "syncMethod" TEXT NOT NULL, + "syncExternalId" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); +INSERT INTO "new_Events" ("createdAt", "id", "name", "shortName", "startsAt", "syncExternalId", "syncMethod", "updatedAt") SELECT "createdAt", "id", "name", "shortName", "startsAt", "syncExternalId", "syncMethod", "updatedAt" FROM "Events"; +DROP TABLE "Events"; +ALTER TABLE "new_Events" RENAME TO "Events"; +CREATE UNIQUE INDEX "Events_shortName_key" ON "Events"("shortName"); +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9f6c215..78cfe69 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -24,7 +24,7 @@ model Events { id String @id @default(uuid()) name String shortName String @unique - startsAt DateTime + startsAt DateTime? syncMethod String syncExternalId String? createdAt DateTime @default(now()) From 4eb9be0d3d5fada350046a1c62318c47f6738a4c Mon Sep 17 00:00:00 2001 From: Keiichiro Amemiya Date: Fri, 14 Jun 2024 19:55:49 +0200 Subject: [PATCH 2/8] favicon --- public/favicon.ico | Bin 0 -> 3290 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 public/favicon.ico diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..93e503790a172e3cea880f98fc1526077eae27ba GIT binary patch literal 3290 zcmd5LFIE`TT?j;N&6(Hf(IV#ST62`FfS z?2Dj|iUq+lV%(D-zD+zyAsevc_$dm6sSfFRp*D4JJPJv-u+RlqVF3!x~=n-qp& z@JO=^-a|21p2KrCF^;DN(aPWMFRXNfCWCnlofIHog1u0bI9ZW3-9s~iAaESV>Vces zINo4Kn9nB#R(Me$)(HW;X7hFz9BA2j@@krI6V^(Sgs*@A!6P;WD-17iq9n-*he1;F z&yAma@UF3~_X8;+i9D1n0lunh7-JQkyRG!d`NGyoXf!{b!N`~<3N|c66oDvtDH=Os zIUcb1PF59G5MislYp(gu+cPuYdA2mN3?)l~O`hj55O_9I3m5NcD!On7y8HZqRN4eU zMN#DUf-w=7mjW8V1yKUNq`*z!%BWSRPTzTPbn0d9i5ox$86bn3lar!(1-Zw1E3eFy ze0H~>Wg=Emv62O}Xy~ekI3}FI$A)bdJYzpAWXOiBcB*==yi53<*tv)(5 zkm(z81;@&-F74@mzVrGL@V9qAD(`%-2@&x!U}qiB#WkHApBqpd;)H}OT~%R zaP~nSWB4D;p_$Z1U!*3>n#j;cUFN7mAC`B0S(|vfv+wJQ-ucR&$J-LKWmoT&T)q=O zF-sR+Q5`du|t;ohrNdAl`O={mC&SSd{4vsK^~vCRyPNMKs@PBoA!C zKb(N~Po};5L>u287O}}m&{H3^U-W?rcV-po!i@STj36##I8okc7*P>OA zirelMoxig#e(XcndQ}ymcA#~Q;Y5(6-{Rw}=a82UX_H)l&h20s(O?J&>Vaq*ePHD@B-V!(#_#_G-i73DjwgAtd zd^s2{9NSRVvvB(9e-6+7yK3akrsk(w#rW35le(cFYc9QWZ2WxXny&cqAF8^atvx!P z9_olz&z4-6k2H_?az9<+*+uw^I5mc8`U5D8B!3v%i+Yl#M-QCuY8Y57y)=>6_!U=h zGfN%GREGH-H|nqdiu~7V2hz+wdDGpB&V{nev#~#qZ8>*8T08H^?epiHOm$bPDz9mF z@dSBf3z!?0i7k-x3%_A&rfFg?>FgOPyW8QL$g;-Mb2=(pe{L9flXGG^(;S3`nud0F zJzG~d=Zf`Y=o71qN#EM0RQF~@;b4LU5k~-G7}$x4UV|Qj3WgA4Psp*A!Z9Pa-Qk;r zriBy8oc)8Zi!aPM{lm7d?ORhlFKn33@ZZcd$1%qY?Of?vha(9W0UvGwdDCYB-?A)H zKXIJ(JbFsrZwuo z=?jd=dd$NFlMb-)$@u~}1pH}^M{~gufTC`ymcEM0(SloDfhnhdG9!2`yYg|}z{~RX zuf5?BcL;!^P~bz^P=A)zDTs1e9ulXL?ai(cSRFDYyK zGeTb&CA0g!e6h7-k&2GEvj^R)N8zO`c+Wp&u4`T4-7AW;EZZj(p25jQ)mB2t68~Dzl2jIOsfoq$(?N3;26)zC;P4*Nl3?LoWX~lnM>I`~#YAgO>}U z_}leg!|4){mWIzC2xY?xLV!TvB4G!YXVII|19=B8-)OvkKYH*&Fc?J9Tcy^-wqLBd z@hX0K$&)>STIUIlfxi{r>k;fT1w~H6?cfHHR1Nrcan|8$TY!(86j6j|Z(8n-uEk#t zFa5Xf;lB>`-w!vO(XyjvG^gSEHzlppoc{=89nu4vc{LBPhGC})5tzUL-cW#VT1a~+ z5pu)f7zTaYDe9Zbcf_yUZJzn*z{B6_@BOo`Zz0;8IMnxW?SVFd^B9_dI)-X&1w%3l z{(Av`v{!-*M-hBt8vO11N%DpRH=>$)SRtGf3)i(A)mNkk>n)(3qHq8L#bOGNBomZk*ecXU^Q|NVtYO*b`!@X2$dM;At?;Y;R<1wXvvNg-oX&~kvT{J z@Zp28%~g#Bt)tb~7AmhlElVtvw$Gs#R2)39g0qkqxK?2~Ku8C-q2A+zKk2_{G{iI+ z;0W0LR8dh9fdIeJsxP{+IQRIqn$KtB9do#%?E2*FA88X8QluXQc}`3q$w|XS&B<~) za6h5Y1ArsRxH*FZJVyF5x!1uW7TP3vHl5S*wpDFz87ew+D-_GmpajIu250RnH$E{F z10Y}(pm487h;gljCxMCWEDP?=n3nV&xeQ}1b`3O?M4ODFlCz2Vc!N4@yMm(dh+8_K Opjh(z{|Ek`p8p4QuBfK~ literal 0 HcmV?d00001 From 95bb78ffdde7b8567c50dc1b546f96cd3c25424d Mon Sep 17 00:00:00 2001 From: Keiichiro Amemiya Date: Fri, 14 Jun 2024 19:56:41 +0200 Subject: [PATCH 3/8] favicon --- app/root.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/root.tsx b/app/root.tsx index b43ba37..1e348d4 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -21,7 +21,9 @@ export const meta: MetaFunction = () => [ { name: "viewport", content: "width=device-width, initial-scale=1" }, ]; -export const links: LinksFunction = () => [{ rel: "icon", href: "data:," }]; +export const links: LinksFunction = () => [ + { rel: "icon", href: "/favicon.ico" }, +]; export const loader = async ({ request, context }: LoaderFunctionArgs) => { const cookieHeader = request.headers.get("Cookie"); From e685c169c11ef883070675ab959403359368d77a Mon Sep 17 00:00:00 2001 From: Keiichiro Amemiya Date: Fri, 14 Jun 2024 19:57:26 +0200 Subject: [PATCH 4/8] or this --- app/root.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/root.tsx b/app/root.tsx index 1e348d4..03d35ad 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -21,9 +21,7 @@ export const meta: MetaFunction = () => [ { name: "viewport", content: "width=device-width, initial-scale=1" }, ]; -export const links: LinksFunction = () => [ - { rel: "icon", href: "/favicon.ico" }, -]; +export const links: LinksFunction = () => []; export const loader = async ({ request, context }: LoaderFunctionArgs) => { const cookieHeader = request.headers.get("Cookie"); From 595bd82e44daa82014066d770db2bd722b2b61ab Mon Sep 17 00:00:00 2001 From: Keiichiro Amemiya Date: Fri, 14 Jun 2024 20:30:05 +0200 Subject: [PATCH 5/8] favicon --- app/root.tsx | 4 +++- public/_headers | 2 ++ public/_routes.json | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/root.tsx b/app/root.tsx index 03d35ad..1e348d4 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -21,7 +21,9 @@ export const meta: MetaFunction = () => [ { name: "viewport", content: "width=device-width, initial-scale=1" }, ]; -export const links: LinksFunction = () => []; +export const links: LinksFunction = () => [ + { rel: "icon", href: "/favicon.ico" }, +]; export const loader = async ({ request, context }: LoaderFunctionArgs) => { const cookieHeader = request.headers.get("Cookie"); diff --git a/public/_headers b/public/_headers index ae0670c..f9e2777 100644 --- a/public/_headers +++ b/public/_headers @@ -1,2 +1,4 @@ +/favicon.ico + Cache-Control: public, max-age=3600, s-maxage=3600 /assets/* Cache-Control: public, max-age=31536000, immutable diff --git a/public/_routes.json b/public/_routes.json index 242c517..b042b3e 100644 --- a/public/_routes.json +++ b/public/_routes.json @@ -1,5 +1,5 @@ { - "version": 1, - "include": ["/*"], - "exclude": ["/assets/*"] + "version": 1, + "include": ["/*"], + "exclude": ["/favicon.ico", "/assets/*"] } From af7036e6b3be2d830596a711b217789acacdab37 Mon Sep 17 00:00:00 2001 From: Keiichiro Amemiya Date: Fri, 14 Jun 2024 20:36:00 +0200 Subject: [PATCH 6/8] title --- app/root.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/app/root.tsx b/app/root.tsx index 1e348d4..3842253 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -46,6 +46,7 @@ export const Layout = ({ children }: PropsWithChildren) => { return ( + Japanese Restream From aed69d52ea23781cb0289eab8f75fddb12ea3a0c Mon Sep 17 00:00:00 2001 From: Keiichiro Amemiya Date: Fri, 14 Jun 2024 20:36:18 +0200 Subject: [PATCH 7/8] react-admin List override --- app/routes/admin.$/components/override.tsx | 5 +++++ app/routes/admin.$/resources/events.tsx | 3 +-- app/routes/admin.$/resources/runs.tsx | 4 +--- app/routes/admin.$/resources/users.tsx | 3 +-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/routes/admin.$/components/override.tsx b/app/routes/admin.$/components/override.tsx index daf28f5..41c4524 100644 --- a/app/routes/admin.$/components/override.tsx +++ b/app/routes/admin.$/components/override.tsx @@ -4,6 +4,7 @@ import { Create as RaCreate, Datagrid as RaDatagrid, Edit as RaEdit, + List as RaList, } from "react-admin"; export const Datagrid = (props: ComponentProps) => { @@ -23,3 +24,7 @@ export const Edit = (props: ComponentProps) => { export const Create = (props: ComponentProps) => { return ; }; + +export const List = (props: ComponentProps) => { + return ; +}; diff --git a/app/routes/admin.$/resources/events.tsx b/app/routes/admin.$/resources/events.tsx index 9cb2740..2af160f 100644 --- a/app/routes/admin.$/resources/events.tsx +++ b/app/routes/admin.$/resources/events.tsx @@ -2,7 +2,6 @@ import { useFetcher } from "@remix-run/react"; import { DateField, DateTimeInput, - List, Resource, SelectInput, SimpleForm, @@ -12,7 +11,7 @@ import { } from "react-admin"; import { syncOptions } from "../../../lib/api/sync-options"; -import { Create, Datagrid, Edit } from "../components/override"; +import { Create, Datagrid, Edit, List } from "../components/override"; const EventsList = () => { return ( diff --git a/app/routes/admin.$/resources/runs.tsx b/app/routes/admin.$/resources/runs.tsx index a1c1748..e36d8f6 100644 --- a/app/routes/admin.$/resources/runs.tsx +++ b/app/routes/admin.$/resources/runs.tsx @@ -1,7 +1,6 @@ import { DateField, DateTimeInput, - List, ReferenceField, ReferenceInput, Resource, @@ -11,11 +10,10 @@ import { UrlField, } from "react-admin"; -import { Datagrid, Edit } from "../components/override"; +import { Datagrid, Edit, List } from "../components/override"; const RunsList = () => ( ]} > diff --git a/app/routes/admin.$/resources/users.tsx b/app/routes/admin.$/resources/users.tsx index 360d7f8..2f3c527 100644 --- a/app/routes/admin.$/resources/users.tsx +++ b/app/routes/admin.$/resources/users.tsx @@ -1,14 +1,13 @@ import { BooleanField, BooleanInput, - List, Resource, SimpleForm, TextField, TextInput, } from "react-admin"; -import { Datagrid, Edit } from "../components/override"; +import { Datagrid, Edit, List } from "../components/override"; const UsersList = () => ( From cd7e131426c6ef041fd3bc4f60d5c644f9ac3f69 Mon Sep 17 00:00:00 2001 From: Keiichiro Amemiya Date: Fri, 14 Jun 2024 21:07:53 +0200 Subject: [PATCH 8/8] esa sync --- app/lib/api/esa-horaro/index.ts | 26 + app/lib/api/esa-horaro/sample-schedule.json | 2439 +++++++++++++++++++ app/lib/api/sync-options.ts | 1 + app/routes/admin.$/resources/events.tsx | 2 + app/routes/admin.sync.tsx | 5 + 5 files changed, 2473 insertions(+) create mode 100644 app/lib/api/esa-horaro/index.ts create mode 100644 app/lib/api/esa-horaro/sample-schedule.json diff --git a/app/lib/api/esa-horaro/index.ts b/app/lib/api/esa-horaro/index.ts new file mode 100644 index 0000000..b8bde67 --- /dev/null +++ b/app/lib/api/esa-horaro/index.ts @@ -0,0 +1,26 @@ +import ky from "ky"; + +import type sampleSchedule from "./sample-schedule.json"; + +export const esaHoraro = async (eventSlug: string) => { + const result = await ky + .get(`https://horaro.org/-/api/v1/events/esa/schedules/${eventSlug}`) + .json(); + + const nameColumnIndex = result.data.columns.indexOf("Game"); + const categoryColumnIndex = result.data.columns.indexOf("Category"); + const platformColumnIndex = result.data.columns.indexOf("Platform"); + + return result.data.items.map((item) => { + const name = item.data[nameColumnIndex]; + const category = item.data[categoryColumnIndex]; + const platform = item.data[platformColumnIndex]; + return { + id: name && category ? `${name} - ${category}` : crypto.randomUUID(), + name: name ?? "Unknown", + category, + playedWith: platform, + startsAt: new Date(item.scheduled), + }; + }); +}; diff --git a/app/lib/api/esa-horaro/sample-schedule.json b/app/lib/api/esa-horaro/sample-schedule.json new file mode 100644 index 0000000..03b8f6e --- /dev/null +++ b/app/lib/api/esa-horaro/sample-schedule.json @@ -0,0 +1,2439 @@ +{ + "data": { + "id": "1d11cdbel357987af0", + "name": "2019 (Stream One)", + "slug": "2019-one", + "timezone": "Europe/Berlin", + "start": "2019-07-20T14:00:00+02:00", + "start_t": 1563624000, + "website": "https://esamarathon.com/", + "twitter": "esamarathon", + "twitch": "esamarathon", + "description": "ESA Summer 2019 is a speedrunning centred community meet-up and marathon. The doors of the event area at the Quality Hotel View in Malmö are open from Friday the 19th of July until Sunday the 28th of July.\r\n\r\nFor quick reference, you may be most interested in the following links: \r\n[Master Info Post](https://esamarathon.com/news/f9a15baf-3c7d-439b-ad85-148b640f45a1) \r\n[Stream Two Schedule](https://horaro.org/esa/2019-two)\r\n\r\nSETUP Games: These are buffer blocks that give us an opportunity to tackle delays. The games will be played in their specified timeslot if the marathon is not too far behind the original schedule at that point. If we are, they will be pushed to the last day of the 2nd stream. Decisions will be made several hours before the run is scheduled. That means all SETUP Games will definitely get shown.", + "setup": "PT10M", + "setup_t": 600, + "updated": "2019-11-15T21:13:30Z", + "hidden_columns": ["Layout", "Info", "ID"], + "link": "https://horaro.org/esa/2019-one", + "columns": [ + "Game", + "Player(s)", + "Platform", + "Category", + "Note", + "Layout", + "Info", + "ID" + ], + "items": [ + { + "length": "PT40M", + "length_t": 2400, + "scheduled": "2019-07-20T14:00:00+02:00", + "scheduled_t": 1563624000, + "data": [ + "Marbles On Stream", + "360Chrism", + "PC", + "Viewer Races", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-20T14:50:00+02:00", + "scheduled_t": 1563627000, + "data": [ + "Perfect Dark", + "ThaRixer", + "N64", + "Any% (Agent)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT50M", + "length_t": 3000, + "scheduled": "2019-07-20T15:35:00+02:00", + "scheduled_t": 1563629700, + "data": [ + "Banjo-Tooie", + "Xafication", + "N64", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H10M", + "length_t": 4200, + "scheduled": "2019-07-20T16:35:00+02:00", + "scheduled_t": 1563633300, + "data": [ + "Guacamelee! 2", + "Chfou", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT45M", + "length_t": 2700, + "scheduled": "2019-07-20T17:55:00+02:00", + "scheduled_t": 1563638100, + "data": [ + "Freedom Planet", + "Revolucion", + "PC", + "Lilac", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT45M", + "length_t": 2700, + "scheduled": "2019-07-20T18:50:00+02:00", + "scheduled_t": 1563641400, + "data": [ + "Kirby: Nightmare in Dreamland", + "Kinnin11", + "GBP", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT24M", + "length_t": 1440, + "scheduled": "2019-07-20T19:45:00+02:00", + "scheduled_t": 1563644700, + "data": [ + "Mamono Hunter Yohko", + "btrim vs. TheMotherBrain86 vs. JkL87", + "Genesis", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT25M", + "length_t": 1500, + "scheduled": "2019-07-20T20:19:00+02:00", + "scheduled_t": 1563646740, + "data": [ + "Chip \u0027n Dale: Rescue Rangers 2", + "Kaadzik", + "NES", + "Any% (One Player)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT10M", + "length_t": 600, + "scheduled": "2019-07-20T20:54:00+02:00", + "scheduled_t": 1563648840, + "data": [ + "Solstice: Quest for the Staff of Demnos", + "Jokaah vs. Niss3 vs. EndySWE", + "NES", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT22M", + "length_t": 1320, + "scheduled": "2019-07-20T21:14:00+02:00", + "scheduled_t": 1563650040, + "data": [ + "Bionic Commando", + "duckfist", + "NES", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-20T21:46:00+02:00", + "scheduled_t": 1563651960, + "data": [ + "Blaster Master", + "BigJon", + "NES", + "Any% JP (150% Game Speed)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-20T22:31:00+02:00", + "scheduled_t": 1563654660, + "data": [ + "Touhou Luna Nights", + "snapcase_ vs. DrimFox", + "PC", + "Any% (No Major Skips)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-20T23:16:00+02:00", + "scheduled_t": 1563657360, + "data": [ + "Touhou: Scarlet Curiosity", + "Naro", + "PC", + "Remilia All Bosses", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT25M", + "length_t": 1500, + "scheduled": "2019-07-21T00:01:00+02:00", + "scheduled_t": 1563660060, + "data": [ + "Katana Zero", + "Kainalo vs. yisk", + "PC", + "All Stages", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT30M", + "length_t": 1800, + "scheduled": "2019-07-21T00:36:00+02:00", + "scheduled_t": 1563662160, + "data": [ + "Hotline Miami", + "Jackintoshh", + "PC", + "All Levels", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H10M", + "length_t": 4200, + "scheduled": "2019-07-21T01:16:00+02:00", + "scheduled_t": 1563664560, + "data": ["SOMA", "ItsTrigger", "PC", "Any%", null, null, null, null], + "options": null + }, + { + "length": "PT50M", + "length_t": 3000, + "scheduled": "2019-07-21T02:36:00+02:00", + "scheduled_t": 1563669360, + "data": [ + "Silent Hill 2", + "Punchi", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H30M", + "length_t": 5400, + "scheduled": "2019-07-21T03:36:00+02:00", + "scheduled_t": 1563672960, + "data": [ + "Devil May Cry 4: Special Edition", + "Mekarazium", + "PC", + "Nero/Dante NG Devil Hunter", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H", + "length_t": 7200, + "scheduled": "2019-07-21T05:16:00+02:00", + "scheduled_t": 1563678960, + "data": [ + "Stardew Valley", + "Jazzy, Venomynous", + "PC", + "Pantry (Glitchless, Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H10M", + "length_t": 4200, + "scheduled": "2019-07-21T07:26:00+02:00", + "scheduled_t": 1563686760, + "data": [ + "Pikmin", + "Mokaygee", + "GCN", + "All Parts", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H25M", + "length_t": 5100, + "scheduled": "2019-07-21T08:46:00+02:00", + "scheduled_t": 1563691560, + "data": [ + "BattleBlock Theater", + "GameguySD", + "PC", + "Any% (No Level Skips, Insane)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H", + "length_t": 3600, + "scheduled": "2019-07-21T10:21:00+02:00", + "scheduled_t": 1563697260, + "data": [ + "Minecraft: Java Edition", + "Joshimuz vs. Trollbear666", + "PC", + "Bingo (Single, Medium)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT40M", + "length_t": 2400, + "scheduled": "2019-07-21T11:31:00+02:00", + "scheduled_t": 1563701460, + "data": [ + "The Secret of Monkey Island", + "Firepaw", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT25M", + "length_t": 1500, + "scheduled": "2019-07-21T12:21:00+02:00", + "scheduled_t": 1563704460, + "data": [ + "Day of the Tentacle Remastered", + "NoobSalmon", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT18M", + "length_t": 1080, + "scheduled": "2019-07-21T12:56:00+02:00", + "scheduled_t": 1563706560, + "data": [ + "realMyst: Masterpiece Edition", + "Gelly", + "PC", + "All Pages", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H", + "length_t": 3600, + "scheduled": "2019-07-21T13:24:00+02:00", + "scheduled_t": 1563708240, + "data": [ + "Ultima IX: Ascension", + "ElCidDK", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT22M", + "length_t": 1320, + "scheduled": "2019-07-21T14:34:00+02:00", + "scheduled_t": 1563712440, + "data": [ + "Gothic", + "PokerFacowaty", + "PC", + "No OoB", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT43M", + "length_t": 2580, + "scheduled": "2019-07-21T15:06:00+02:00", + "scheduled_t": 1563714360, + "data": [ + "The Elder Scrolls IV: Oblivion", + "NoobSalmon", + "PC", + "No OoB", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H20M", + "length_t": 4800, + "scheduled": "2019-07-21T15:59:00+02:00", + "scheduled_t": 1563717540, + "data": [ + "Monster Hunter World", + "Team Darkside", + "PS4", + "Showcase", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT48M", + "length_t": 2880, + "scheduled": "2019-07-21T17:29:00+02:00", + "scheduled_t": 1563722940, + "data": [ + "The Legend of Zelda: Breath of the Wild", + "Linkus7", + "Switch", + "Any% (No Amiibo)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H35M", + "length_t": 5700, + "scheduled": "2019-07-21T18:27:00+02:00", + "scheduled_t": 1563726420, + "data": [ + "Celeste", + "TGH_sr", + "PC", + "All Chapters", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H10M", + "length_t": 4200, + "scheduled": "2019-07-21T20:12:00+02:00", + "scheduled_t": 1563732720, + "data": [ + "Tomb Raider: The Last Revelation", + "Cadarev", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H05M", + "length_t": 3900, + "scheduled": "2019-07-21T21:32:00+02:00", + "scheduled_t": 1563737520, + "data": [ + "Prince of Persia: The Two Thrones", + "catalystz", + "PC", + "Any% (Normal)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT50M", + "length_t": 3000, + "scheduled": "2019-07-21T22:47:00+02:00", + "scheduled_t": 1563742020, + "data": [ + "Asghan: The Dragon Slayer", + "havrd", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-21T23:47:00+02:00", + "scheduled_t": 1563745620, + "data": [ + "Penumbra: Black Plague", + "TheKotti", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT3H05M", + "length_t": 11100, + "scheduled": "2019-07-22T00:32:00+02:00", + "scheduled_t": 1563748320, + "data": [ + "The Last of Us", + "AnthonyCaliber", + "PS4", + "New Game (Grounded, Glitchless)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H25M", + "length_t": 5100, + "scheduled": "2019-07-22T03:47:00+02:00", + "scheduled_t": 1563760020, + "data": [ + "Resident Evil 4", + "Call_me_Zeroo", + "PC", + "NG+", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H10M", + "length_t": 4200, + "scheduled": "2019-07-22T05:22:00+02:00", + "scheduled_t": 1563765720, + "data": [ + "Octopath Traveler", + "Xoneris, yisk", + "PC", + "Single Story (Bid War)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT3H10M", + "length_t": 11400, + "scheduled": "2019-07-22T06:42:00+02:00", + "scheduled_t": 1563770520, + "data": [ + "Need For Speed: The Run", + "Kuru", + "PC", + "Any% (Extreme)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT15M", + "length_t": 900, + "scheduled": "2019-07-22T10:02:00+02:00", + "scheduled_t": 1563782520, + "data": [ + "Paris Marseille Racing", + "linkboss vs. Shigan_ vs. Gamonymous__", + "PS1", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT13M", + "length_t": 780, + "scheduled": "2019-07-22T10:27:00+02:00", + "scheduled_t": 1563784020, + "data": [ + "The Last Ninja", + "skateman222", + "NES", + "Beat the game", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT05M", + "length_t": 300, + "scheduled": "2019-07-22T10:50:00+02:00", + "scheduled_t": 1563785400, + "data": [ + "King Kong 2: Ikari no Megaton Punch", + "Apollo22237", + "NES", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT14M", + "length_t": 840, + "scheduled": "2019-07-22T11:05:00+02:00", + "scheduled_t": 1563786300, + "data": ["Tennis", "JkL87", "NES", "Level 3", null, null, null, null], + "options": null + }, + { + "length": "PT12M", + "length_t": 720, + "scheduled": "2019-07-22T11:29:00+02:00", + "scheduled_t": 1563787740, + "data": [ + "Indiana Jones and the Last Crusade", + "TheMotherBrain86", + "NES", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT01M", + "length_t": 60, + "scheduled": "2019-07-22T11:51:00+02:00", + "scheduled_t": 1563789060, + "data": [ + "Urban Champion", + "JkL87", + "NES", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT10M", + "length_t": 600, + "scheduled": "2019-07-22T12:02:00+02:00", + "scheduled_t": 1563789720, + "data": [ + "Joe \u0026 Mac", + "EndySWE", + "NES", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT08M", + "length_t": 480, + "scheduled": "2019-07-22T12:22:00+02:00", + "scheduled_t": 1563790920, + "data": [ + "DuckTales", + "garadas21", + "NES", + "Any% (1p2c)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT13M", + "length_t": 780, + "scheduled": "2019-07-22T12:40:00+02:00", + "scheduled_t": 1563792000, + "data": [ + "Karnov", + "Apollo22237", + "NES", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT05M", + "length_t": 300, + "scheduled": "2019-07-22T13:03:00+02:00", + "scheduled_t": 1563793380, + "data": [ + "Die Hard", + "Lucha_Gym", + "NES", + "Any% (Beginner)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT15M", + "length_t": 900, + "scheduled": "2019-07-22T13:18:00+02:00", + "scheduled_t": 1563794280, + "data": [ + "Code Name: Viper", + "TheMotherBrain86", + "NES", + "Any% (Easy)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT09M", + "length_t": 540, + "scheduled": "2019-07-22T13:43:00+02:00", + "scheduled_t": 1563795780, + "data": ["Trojan", "Dxtr", "NES", "Any%", null, null, null, null], + "options": null + }, + { + "length": "PT07M", + "length_t": 420, + "scheduled": "2019-07-22T14:02:00+02:00", + "scheduled_t": 1563796920, + "data": ["Jaws", "EndySWE", "NES", "Any%", null, null, null, null], + "options": null + }, + { + "length": "PT16M", + "length_t": 960, + "scheduled": "2019-07-22T14:19:00+02:00", + "scheduled_t": 1563797940, + "data": [ + "Fallout 2", + "JackofHearts", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT32M", + "length_t": 1920, + "scheduled": "2019-07-22T14:45:00+02:00", + "scheduled_t": 1563799500, + "data": [ + "Fallout: New Vegas", + "kungkobra", + "PC", + "Glitchless", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT40M", + "length_t": 2400, + "scheduled": "2019-07-22T15:27:00+02:00", + "scheduled_t": 1563802020, + "data": [ + "Serious Sam 3", + "Gelly, apple1417", + "PC", + "Any% Tourist (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-22T16:17:00+02:00", + "scheduled_t": 1563805020, + "data": [ + "Half-Life", + "qDTH", + "PC", + "Any% (Scripted)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H10M", + "length_t": 4200, + "scheduled": "2019-07-22T17:02:00+02:00", + "scheduled_t": 1563807720, + "data": [ + "Half-Life 2", + "maltemller", + "PC", + "New Engine Inbounds", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-22T18:22:00+02:00", + "scheduled_t": 1563812520, + "data": [ + "Portal 2", + "Goodigo, Wilbo__", + "PC", + "Any% (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H15M", + "length_t": 4500, + "scheduled": "2019-07-22T19:07:00+02:00", + "scheduled_t": 1563815220, + "data": [ + "Grand Theft Auto III", + "UltimaOmega07", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H30M", + "length_t": 5400, + "scheduled": "2019-07-22T20:32:00+02:00", + "scheduled_t": 1563820320, + "data": [ + "I Wanna Find My Destiny", + "BBF_", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H", + "length_t": 3600, + "scheduled": "2019-07-22T22:12:00+02:00", + "scheduled_t": 1563826320, + "data": [ + "I Wanna Take The Timemachine 2", + "Naloas", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT26M", + "length_t": 1560, + "scheduled": "2019-07-22T23:22:00+02:00", + "scheduled_t": 1563830520, + "data": [ + "Point Blank Trilogy", + "Naegleria", + "PS2", + "Insane", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT4H20M", + "length_t": 15600, + "scheduled": "2019-07-22T23:58:00+02:00", + "scheduled_t": 1563832680, + "data": [ + "Final Fantasy X-2", + "Leonis07 vs. Metako", + "PS2", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT3H25M", + "length_t": 12300, + "scheduled": "2019-07-23T04:28:00+02:00", + "scheduled_t": 1563848880, + "data": [ + "The World Ends With You: Final Remix", + "Punchi", + "Switch", + "Any% (Normal)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT3H35M", + "length_t": 12900, + "scheduled": "2019-07-23T08:03:00+02:00", + "scheduled_t": 1563861780, + "data": [ + "Kingdom Hearts III", + "Kayarune vs. desa3579", + "PS4", + "Any% (Beginner)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H", + "length_t": 3600, + "scheduled": "2019-07-23T11:48:00+02:00", + "scheduled_t": 1563875280, + "data": [ + "Link: The Faces of Evil", + "Grumpmeister", + "Philips CD-i", + "All Cutscenes", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT13M", + "length_t": 780, + "scheduled": "2019-07-23T12:58:00+02:00", + "scheduled_t": 1563879480, + "data": [ + "Dora the Explorer: Dora\u0027s World Adventure", + "Mr_Brood", + "GBA", + "Story Mode", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT25M", + "length_t": 1500, + "scheduled": "2019-07-23T13:21:00+02:00", + "scheduled_t": 1563880860, + "data": [ + "Nintendogs", + "ZooKetra", + "Nintendo DS", + "All Beginner Golds", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT20M", + "length_t": 1200, + "scheduled": "2019-07-23T13:56:00+02:00", + "scheduled_t": 1563882960, + "data": [ + "Mega Game 1", + "Samura1man vs. iKainalo", + "PC", + "Beat the game", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT08M", + "length_t": 480, + "scheduled": "2019-07-23T14:26:00+02:00", + "scheduled_t": 1563884760, + "data": [ + "I am Bread", + "YanoKarozuno", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT11M", + "length_t": 660, + "scheduled": "2019-07-23T14:44:00+02:00", + "scheduled_t": 1563885840, + "data": [ + "Red Lake", + "carska", + "PC", + "Any% (Skip Chapter 5)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT20M", + "length_t": 1200, + "scheduled": "2019-07-23T15:05:00+02:00", + "scheduled_t": 1563887100, + "data": ["Bugdom", "Jitaenow", "PC", "Any%", null, null, null, null], + "options": null + }, + { + "length": "PT15M", + "length_t": 900, + "scheduled": "2019-07-23T15:35:00+02:00", + "scheduled_t": 1563888900, + "data": [ + "hhGregg\u0027s Quest for Coupons", + "iKainalo", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT04M", + "length_t": 240, + "scheduled": "2019-07-23T16:00:00+02:00", + "scheduled_t": 1563890400, + "data": [ + "Jelly Mario", + "JustTor", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H", + "length_t": 3600, + "scheduled": "2019-07-23T16:14:00+02:00", + "scheduled_t": 1563891240, + "data": [ + "Awful Games", + "havrd \u0026 Friends", + "PC", + "Relay", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT40M", + "length_t": 2400, + "scheduled": "2019-07-23T17:24:00+02:00", + "scheduled_t": 1563895440, + "data": [ + "Street Boyz", + "ThaRixer , Punchi , Jptje vs. SixRockFire , WarDrumsGaming , RebelDragon95", + "PS2", + "NG+ All Levels", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H", + "length_t": 7200, + "scheduled": "2019-07-23T18:14:00+02:00", + "scheduled_t": 1563898440, + "data": [ + "Borderlands 2", + "Mr_Brood , Goodigo", + "PC", + "Any% (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT30M", + "length_t": 1800, + "scheduled": "2019-07-23T20:24:00+02:00", + "scheduled_t": 1563906240, + "data": [ + "Divinity: Original Sin II", + "Cropax , MrWalrus3451", + "PC", + "Any% (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H40M", + "length_t": 6000, + "scheduled": "2019-07-23T21:04:00+02:00", + "scheduled_t": 1563908640, + "data": [ + "Hearthstone: Blackrock Mountain", + "srd_27", + "PC", + "Heroic", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT30M", + "length_t": 1800, + "scheduled": "2019-07-23T22:54:00+02:00", + "scheduled_t": 1563915240, + "data": [ + "Yu-Gi-Oh! Forbidden Memories", + "Mergy", + "PS1", + "Showcase", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H", + "length_t": 7200, + "scheduled": "2019-07-23T23:34:00+02:00", + "scheduled_t": 1563917640, + "data": [ + "Pokemon Crystal Randomizer", + "360Chrism", + "PC", + "Beat Lance", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H40M", + "length_t": 6000, + "scheduled": "2019-07-24T01:44:00+02:00", + "scheduled_t": 1563925440, + "data": [ + "Advance Wars: Dual Strike", + "SirFrozer", + "Nintendo DS", + "Any% Skills", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H25M", + "length_t": 5100, + "scheduled": "2019-07-24T03:34:00+02:00", + "scheduled_t": 1563932040, + "data": [ + "Splatoon 2", + "Isaia", + "Switch", + "Octo Expansion Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT55M", + "length_t": 3300, + "scheduled": "2019-07-24T05:09:00+02:00", + "scheduled_t": 1563937740, + "data": [ + "Learn with Pokémon: Typing Adventure", + "ShadowFrost", + "Nintendo DS", + "Catch Mew", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT30M", + "length_t": 1800, + "scheduled": "2019-07-24T06:14:00+02:00", + "scheduled_t": 1563941640, + "data": [ + "The Typing of the Dead", + "pulla", + "PC", + "Arcade", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT20M", + "length_t": 1200, + "scheduled": "2019-07-24T06:54:00+02:00", + "scheduled_t": 1563944040, + "data": [ + "Let\u0027s Tap", + "skateman222 vs. Christerious", + "Wii", + "Tap Runner", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-24T07:24:00+02:00", + "scheduled_t": 1563945840, + "data": [ + "Darkest Dungeon", + "Tricrow vs. yisk vs. RebelDragon95", + "PC", + "Swine Prince", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H20M", + "length_t": 4800, + "scheduled": "2019-07-24T08:09:00+02:00", + "scheduled_t": 1563948540, + "data": [ + "Halo 2", + "TehSorix , Dubhzo", + "Xbox360", + "Easy (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H", + "length_t": 3600, + "scheduled": "2019-07-24T09:39:00+02:00", + "scheduled_t": 1563953940, + "data": [ + "Owlboy", + "Jitaenow", + "PC", + "All Bosses", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H20M", + "length_t": 8400, + "scheduled": "2019-07-24T10:49:00+02:00", + "scheduled_t": 1563958140, + "data": [ + "Rise of the Tomb Raider", + "Pikkufighter vs. Leemyy vs. genesisprobestream", + "PC", + "Any% (Glitchless)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT55M", + "length_t": 3300, + "scheduled": "2019-07-24T13:19:00+02:00", + "scheduled_t": 1563967140, + "data": [ + "Tomb Raider: Legend", + "RandomPinkBunny vs. rythin_sr", + "PC", + "Any% (No Bug Jump)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT25M", + "length_t": 1500, + "scheduled": "2019-07-24T14:24:00+02:00", + "scheduled_t": 1563971040, + "data": [ + "Yoshi\u0027s Story", + "LoveBot", + "Wii VC", + "All Melons 1-Lap", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT45M", + "length_t": 2700, + "scheduled": "2019-07-24T14:59:00+02:00", + "scheduled_t": 1563973140, + "data": [ + "Spark the Electric Jester 2", + "Argick", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT55M", + "length_t": 3300, + "scheduled": "2019-07-24T15:54:00+02:00", + "scheduled_t": 1563976440, + "data": [ + "Sonic Mania Plus", + "Oldclov", + "PC", + "Knuckles", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT30M", + "length_t": 1800, + "scheduled": "2019-07-24T16:59:00+02:00", + "scheduled_t": 1563980340, + "data": [ + "Sonic the Hedgehog (1991)", + "SuperSonic71087", + "Genesis", + "Beat The Game (Glitchless)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT12M", + "length_t": 720, + "scheduled": "2019-07-24T17:39:00+02:00", + "scheduled_t": 1563982740, + "data": [ + "Chip \u0027N Dale: Rescue Rangers", + "sinister1 , EndySWE", + "NES", + "Any% (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT13M", + "length_t": 780, + "scheduled": "2019-07-24T18:01:00+02:00", + "scheduled_t": 1563984060, + "data": [ + "Contra", + "TheMexicanRunner , Niss3", + "NES", + "Any% (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT15M", + "length_t": 900, + "scheduled": "2019-07-24T18:24:00+02:00", + "scheduled_t": 1563985440, + "data": [ + "Ninja Gaiden", + "ShuriBear vs. Dxtr vs. Duckfist", + "NES", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT30M", + "length_t": 1800, + "scheduled": "2019-07-24T18:49:00+02:00", + "scheduled_t": 1563986940, + "data": [ + "Super Mario Bros. 2 (JP)", + "SuperSonic71087", + "NES", + "Warpless 8-4 FDS", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT38M", + "length_t": 2280, + "scheduled": "2019-07-24T19:29:00+02:00", + "scheduled_t": 1563989340, + "data": [ + "Mega Man 2 Atari Demake", + "BigJon", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT41M", + "length_t": 2460, + "scheduled": "2019-07-24T20:17:00+02:00", + "scheduled_t": 1563992220, + "data": [ + "Mega Man 4", + "Prisiii3 vs. Jokaah", + "NES", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT30M", + "length_t": 1800, + "scheduled": "2019-07-24T21:08:00+02:00", + "scheduled_t": 1563995280, + "data": [ + "Mega Man 1", + "kkorvis \u0026 Friends", + "NES", + "Any% (All Stages)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT20M", + "length_t": 1200, + "scheduled": "2019-07-24T21:48:00+02:00", + "scheduled_t": 1563997680, + "data": [ + "Battletoads (NES)", + "Dxtr, TheMexicanRunner", + "NES", + "Any% (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H30M", + "length_t": 5400, + "scheduled": "2019-07-24T22:18:00+02:00", + "scheduled_t": 1563999480, + "data": [ + "Super Mario Maker 2", + "BigJon, TheHaxor vs. Fuzzyness, SuperSonic71087", + "Switch", + "Co-Op Races", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-24T23:58:00+02:00", + "scheduled_t": 1564005480, + "data": [ + "NES Open Tournament Golf", + "BigJon", + "NES", + "All Courses", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT25M", + "length_t": 1500, + "scheduled": "2019-07-25T00:43:00+02:00", + "scheduled_t": 1564008180, + "data": [ + "Castlevania: Symphony of the Night", + "Dxtr", + "Xbox360", + "Any% (NSC)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT30M", + "length_t": 1800, + "scheduled": "2019-07-25T01:18:00+02:00", + "scheduled_t": 1564010280, + "data": [ + "Bloodstained: Curse of the Moon", + "HaosEdge", + "PC", + "Any% Normal/Veteran", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H", + "length_t": 7200, + "scheduled": "2019-07-25T01:58:00+02:00", + "scheduled_t": 1564012680, + "data": [ + "The Messenger", + "TwoCplus", + "PC", + "Any% (No OoB)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H", + "length_t": 7200, + "scheduled": "2019-07-25T04:08:00+02:00", + "scheduled_t": 1564020480, + "data": [ + "Bayonetta 2", + "Ricyosma", + "Switch", + "Any% (3rd Climax)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT7H40M", + "length_t": 27600, + "scheduled": "2019-07-25T06:18:00+02:00", + "scheduled_t": 1564028280, + "data": [ + "Final Fantasy VII", + "Davesterio", + "PS2", + "Any% (No Slots)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT55M", + "length_t": 3300, + "scheduled": "2019-07-25T14:08:00+02:00", + "scheduled_t": 1564056480, + "data": [ + "Cuphead", + "kalevan_herra, Kirthar vs. SBDWolf, TheMexicanRunner", + "PC", + "Low% (Expert, Current Patch, Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H20M", + "length_t": 4800, + "scheduled": "2019-07-25T15:13:00+02:00", + "scheduled_t": 1564060380, + "data": [ + "Sekiro: Shadows Die Twice", + "Distortion2, SayviTV vs. Ushebti, danflesh111", + "PC", + "All Memories (NG)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-25T16:43:00+02:00", + "scheduled_t": 1564065780, + "data": [ + "Sekiro: Shadows Die Twice", + "Distortion2", + "PC", + "Shura Ending", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT3H20M", + "length_t": 12000, + "scheduled": "2019-07-25T17:28:00+02:00", + "scheduled_t": 1564068480, + "data": [ + "Grand Theft Auto: Vice City", + "KZ_FREW vs. Mhmd_FVC", + "PC", + "All Missions ($25%)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT45M", + "length_t": 2700, + "scheduled": "2019-07-25T20:58:00+02:00", + "scheduled_t": 1564081080, + "data": [ + "SWAT 4", + "Shrimp, Goost91, wakecold, Yvathacal, eidgod, Noobest, coolkid, Tyriounet, zastbat, TheKotti", + "PC", + "All Missions 75+ (Hard, Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT25M", + "length_t": 1500, + "scheduled": "2019-07-25T21:53:00+02:00", + "scheduled_t": 1564084380, + "data": [ + "Doom", + "wakecold vs. Tezur0 vs. Noobest", + "PC", + "Episodes 1-3 - UV Speed", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT35M", + "length_t": 2100, + "scheduled": "2019-07-25T22:28:00+02:00", + "scheduled_t": 1564086480, + "data": [ + "Quake", + "praskOo_ vs. Elgu_ vs. SphereMJ vs. brainfluid", + "PC", + "Easy Run Randomized", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H", + "length_t": 7200, + "scheduled": "2019-07-25T23:13:00+02:00", + "scheduled_t": 1564089180, + "data": [ + "Devil May Cry 5", + "FroobMcGuffin", + "PC", + "Any% (Human)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H45M", + "length_t": 9900, + "scheduled": "2019-07-26T01:23:00+02:00", + "scheduled_t": 1564096980, + "data": [ + "Spyro: Enter the Dragonfly", + "Yeswally1", + "GameCube", + "100%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H25M", + "length_t": 8700, + "scheduled": "2019-07-26T04:18:00+02:00", + "scheduled_t": 1564107480, + "data": [ + "Donkey Kong 64", + "Xafication", + "Wii U VC", + "No Levels Early", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT55M", + "length_t": 3300, + "scheduled": "2019-07-26T06:53:00+02:00", + "scheduled_t": 1564116780, + "data": [ + "Crash Team Racing", + "Nattyo", + "PS2", + "Any% (Warpless)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT40M", + "length_t": 2400, + "scheduled": "2019-07-26T07:58:00+02:00", + "scheduled_t": 1564120680, + "data": [ + "Clustertruck", + "Heinki", + "PC", + "Twitch%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT4H10M", + "length_t": 15000, + "scheduled": "2019-07-26T08:48:00+02:00", + "scheduled_t": 1564123680, + "data": [ + "TrackMania Turbo", + "rioluTM", + "PC", + "All Flags", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H20M", + "length_t": 4800, + "scheduled": "2019-07-26T13:08:00+02:00", + "scheduled_t": 1564139280, + "data": [ + "The Binding of Isaac Afterbirth+", + "YuCaesar, PassionDrama, Gamonymous__, Shigan_, Krakenos, Pingouin23", + "PC", + "Racing+ Season 6", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT19M", + "length_t": 1140, + "scheduled": "2019-07-26T14:38:00+02:00", + "scheduled_t": 1564144680, + "data": [ + "TASBot plays SteamWorld Dig 2", + "dwangoAC", + "Linux", + "Any% by keylie", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT26M", + "length_t": 1560, + "scheduled": "2019-07-26T15:07:00+02:00", + "scheduled_t": 1564146420, + "data": [ + "TASBot plays TAS Showcase", + "dwangoAC", + "Various", + "TAS Showcase", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H", + "length_t": 3600, + "scheduled": "2019-07-26T15:43:00+02:00", + "scheduled_t": 1564148580, + "data": [ + "GeoGuessr", + "Janmumrik vs. havrd vs. TheRedSock", + "PC", + "Scavenger Hunt", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT4H15M", + "length_t": 15300, + "scheduled": "2019-07-26T16:53:00+02:00", + "scheduled_t": 1564152780, + "data": [ + "Dark Souls", + "catalystz", + "PC", + "100%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H30M", + "length_t": 9000, + "scheduled": "2019-07-26T21:18:00+02:00", + "scheduled_t": 1564168680, + "data": [ + "The Witcher 3: Wild Hunt", + "Kaadzik", + "PC", + "Any% (Old Patch)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT4H", + "length_t": 14400, + "scheduled": "2019-07-26T23:58:00+02:00", + "scheduled_t": 1564178280, + "data": [ + "The Legend Of Zelda: Ocarina Of Time", + "BaalNocturno, Amateseru, Fuzzyness", + "N64", + "Randomizer Multiworld (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT38M", + "length_t": 2280, + "scheduled": "2019-07-27T04:08:00+02:00", + "scheduled_t": 1564193280, + "data": [ + "Noobow", + "Crrool", + "GB", + "Beat The Game", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H20M", + "length_t": 4800, + "scheduled": "2019-07-27T04:56:00+02:00", + "scheduled_t": 1564196160, + "data": [ + "Captain Toad: Treasure Tracker", + "Cadarev, tocaloni1", + "Switch", + "Any% (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H07M", + "length_t": 7620, + "scheduled": "2019-07-27T06:26:00+02:00", + "scheduled_t": 1564201560, + "data": [ + "Pokémon Yellow", + "ArayaLoL", + "GBP", + "Any% (Glitchless)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT28M", + "length_t": 1680, + "scheduled": "2019-07-27T08:43:00+02:00", + "scheduled_t": 1564209780, + "data": [ + "Deru: The Art of Cooperation", + "acridstingray3, Ax2u", + "PC", + "Any% (Co-Op)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT20M", + "length_t": 1200, + "scheduled": "2019-07-27T09:21:00+02:00", + "scheduled_t": 1564212060, + "data": [ + "Bastion", + "Kazzadan, HaosEdge, Leonmachar, acridstingray3, Harpa", + "PC", + "5p1c NG Any% No MS", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT18M", + "length_t": 1080, + "scheduled": "2019-07-27T09:51:00+02:00", + "scheduled_t": 1564213860, + "data": [ + "kuso", + "Zet vs. Paulister", + "PC", + "Any%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT15M", + "length_t": 900, + "scheduled": "2019-07-27T10:19:00+02:00", + "scheduled_t": 1564215540, + "data": ["INK", "yajijy", "PC", "Any%", null, null, null, null], + "options": null + }, + { + "length": "PT17M", + "length_t": 1020, + "scheduled": "2019-07-27T10:44:00+02:00", + "scheduled_t": 1564217040, + "data": [ + "VVVVVV", + "mohoc7 vs. tzann", + "PC", + "Glitchless", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT10M", + "length_t": 600, + "scheduled": "2019-07-27T11:11:00+02:00", + "scheduled_t": 1564218660, + "data": [ + "Refunct", + "360Chrism", + "PC", + "Any% + 100%", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT3H", + "length_t": 10800, + "scheduled": "2019-07-27T11:31:00+02:00", + "scheduled_t": 1564219860, + "data": [ + "The Legend of Zelda: A Link to the Past", + "TGH_sr vs. WarpWorldStaff", + "SNES", + "Open Mode (Crowd Control Difficulty)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H", + "length_t": 3600, + "scheduled": "2019-07-27T14:41:00+02:00", + "scheduled_t": 1564231260, + "data": [ + "Super Mario Bros. 3", + "SuperSonic71087 vs. TheHaxor vs. coolkid vs. duckfist", + "NES", + "Any% (Warpless)", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT1H50M", + "length_t": 6600, + "scheduled": "2019-07-27T15:51:00+02:00", + "scheduled_t": 1564235460, + "data": [ + "Super Mario 64", + "cheese", + "N64", + "120 Star", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT20M", + "length_t": 1200, + "scheduled": "2019-07-27T17:51:00+02:00", + "scheduled_t": 1564242660, + "data": [ + "Super Mario 64", + "cheese", + "N64", + "16 Star", + null, + null, + null, + null + ], + "options": null + }, + { + "length": "PT2H30M", + "length_t": 9000, + "scheduled": "2019-07-27T18:21:00+02:00", + "scheduled_t": 1564244460, + "data": [ + "Super Mario Sunshine", + "Team Samura1man vs. Team HiddenPower13", + "Wii", + "Any% Relay", + null, + null, + null, + null + ], + "options": null + } + ], + "links": [ + { + "rel": "self", + "uri": "https://horaro.org/-/api/v1/schedules/1d11cdbel357987af0" + }, + { + "rel": "event", + "uri": "https://horaro.org/-/api/v1/events/7a50r46ezxb6yxb41b" + }, + { + "rel": "ticker", + "uri": "https://horaro.org/-/api/v1/schedules/1d11cdbel357987af0/ticker" + } + ] + } +} diff --git a/app/lib/api/sync-options.ts b/app/lib/api/sync-options.ts index c2b5910..1ad4bd5 100644 --- a/app/lib/api/sync-options.ts +++ b/app/lib/api/sync-options.ts @@ -1,4 +1,5 @@ export const syncOptions = { gdqTracker: "gdq-tracker", rpglbTracker: "rpglb-tracker", + esaHoraro: "esa-horaro", } as const; diff --git a/app/routes/admin.$/resources/events.tsx b/app/routes/admin.$/resources/events.tsx index 2af160f..9fd3b2b 100644 --- a/app/routes/admin.$/resources/events.tsx +++ b/app/routes/admin.$/resources/events.tsx @@ -30,6 +30,8 @@ const EventsList = () => { const syncMethodChoices = [ { id: syncOptions.gdqTracker, name: "GDQ Tracker" }, { id: syncOptions.rpglbTracker, name: "RPGLB Tracker" }, + { id: syncOptions.esaHoraro, name: "ESA Horaro" }, + { id: "none", name: "None" }, ]; const EventsCreate = () => { diff --git a/app/routes/admin.sync.tsx b/app/routes/admin.sync.tsx index 87c6cfc..5ec970e 100644 --- a/app/routes/admin.sync.tsx +++ b/app/routes/admin.sync.tsx @@ -3,6 +3,7 @@ import { type ActionFunctionArgs, json } from "@remix-run/cloudflare"; import { match, P } from "ts-pattern"; import { z } from "zod"; +import { esaHoraro } from "../lib/api/esa-horaro"; import { gdqTracker } from "../lib/api/gdq-tracker"; import { rpglbTracker } from "../lib/api/rpglb-tracker"; import { syncOptions } from "../lib/api/sync-options"; @@ -38,6 +39,10 @@ export const action = async ({ request, context }: ActionFunctionArgs) => { { syncMethod: syncOptions.rpglbTracker, syncExternalId: P.string }, async (event) => rpglbTracker(event.syncExternalId), ) + .with( + { syncMethod: syncOptions.esaHoraro, syncExternalId: P.string }, + async (event) => esaHoraro(event.syncExternalId), + ) .otherwise(() => { throw new Response("unsupported sync method", { status: 400 }); });