add bbb and nhl
parent
5bafa0257b
commit
89f81d7b89
|
@ -0,0 +1 @@
|
|||
The 'work' directory is for your own personal vocabularies.
|
|
@ -0,0 +1 @@
|
|||
/bbb.db
|
|
@ -0,0 +1,29 @@
|
|||
! Copyright (C) 2020 .
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
|
||||
USING: kernel http.server http.server.responses http.server.dispatchers furnace.actions html.forms accessors namespaces io.servers io.sockets.secure.debug ;
|
||||
USING: bonerbonerboner.services ;
|
||||
|
||||
IN: bonerbonerboner
|
||||
|
||||
TUPLE: bbb < dispatcher ;
|
||||
|
||||
: <theme-action> ( -- action )
|
||||
|
||||
<page-action> [ "bbb" "theme" set-value ] >>init
|
||||
|
||||
{ bbb "templates/themes" } >>template ;
|
||||
|
||||
|
||||
: <heartbeat-response> ( -- response )
|
||||
"bonerbonerboner" <text-content> ;
|
||||
|
||||
: <bbb> ( -- responder )
|
||||
bbb new-dispatcher
|
||||
<heartbeat-response> "heartbeat" add-responder ;
|
||||
! <theme-action> "theme" add-responder ;
|
||||
|
||||
SYMBOL: current-test-server
|
||||
: run-test-bbb ( -- )
|
||||
<bbb> main-responder set-global
|
||||
8080 httpd current-test-server set ;
|
|
@ -0,0 +1,53 @@
|
|||
! Copyright (C) 2020 .
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
|
||||
USING: kernel sequences http http.server.dispatchers accessors vocabs.parser furnace.actions regexp db.types db.tuples math urls strings calendar ;
|
||||
USING: bonerbonerboner ;
|
||||
|
||||
IN: bonerbonerboner.services.link-logger
|
||||
|
||||
! TODO: index url and updated date
|
||||
! TODO: add slack integration
|
||||
|
||||
TUPLE: link id url created-by updated-by repost-count date-created date-updated ;
|
||||
|
||||
link "links"
|
||||
{
|
||||
{ "id" "id" +db-assigned-id+ }
|
||||
{ "url" "url" URL }
|
||||
{ "repost-count" "repost_count" INTEGER }
|
||||
{ "created-by" "created_by" TEXT }
|
||||
{ "updated-by" "updated_by" TEXT }
|
||||
{ "date-created" "date_created" TIMESTAMP }
|
||||
{ "date-updated" "date_updated" TIMESTAMP }
|
||||
} define-persistent
|
||||
|
||||
: ensure-link-logger ( -- )
|
||||
[ link ensure-table ] with-bbb-db ;
|
||||
|
||||
: <link> ( url who -- link )
|
||||
[ f ] 2dip dup 0 now dup link boa ;
|
||||
|
||||
: <repost> ( link who -- link )
|
||||
[ dup repost-count>> 1 + >>repost-count ] dip >>updated-by now >>date-updated ;
|
||||
|
||||
: add-link ( url who -- )
|
||||
[ <link> insert-tuple ] with-bbb-db ;
|
||||
|
||||
: update-repost ( link who -- )
|
||||
[ <repost> update-tuple ] with-bbb-db ;
|
||||
|
||||
: repost? ( url -- link/f )
|
||||
link new swap >>url [ select-tuple ] with-bbb-db ;
|
||||
|
||||
: url-regex ( -- regexp )
|
||||
R/ http[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+/i ;
|
||||
|
||||
: strip-urls ( str -- seq )
|
||||
url-regex all-matching-subseqs ;
|
||||
|
||||
: check-repost ( url who -- )
|
||||
[ dup repost? ] dip swap [ update-repost ] [ add-link ] if ;
|
||||
|
||||
! : check-links ( str -- )
|
||||
! strip-urls [ check-repost ] each ;
|
|
@ -0,0 +1,83 @@
|
|||
! Copyright (C) 2020 .
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel math math.ranges math.order math.parser math.functions arrays sequences sequences.extras threads calendar io timers accessors random formatting combinators combinators.random http.server.responses ;
|
||||
USING: prettyprint http furnace.actions http.server.dispatchers ;
|
||||
USING: bonerbonerboner.services.slack ;
|
||||
|
||||
IN: bonerbonerboner.services.mississippis
|
||||
|
||||
CONSTANT: max-mississippi-count 30
|
||||
CONSTANT: min-mississippi-count 1
|
||||
|
||||
: random-stupid-word ( -- something-stupid )
|
||||
{ "balls" "fart" "SIEEEEEEEEEEGE" "hey" "HONESTLY" "fuckface" "it's too late-TOOOOO LATE" }
|
||||
random ;
|
||||
|
||||
: random-m-word ( -- m-word )
|
||||
{ "Minnesota" "Montana" "Marsupial" "Minneapolis" }
|
||||
random ;
|
||||
|
||||
: random-no-word ( -- nope )
|
||||
{ "No can doobie" "Can't do that" "I don't think so, kev" "nope" "Can't, learn the rules" }
|
||||
random ;
|
||||
|
||||
: nonstandard-mississippi-duration ( -- duration )
|
||||
.25 5 uniform-random-float seconds ;
|
||||
|
||||
: standard-mississippi-duration ( -- duration )
|
||||
1 seconds ;
|
||||
|
||||
: nonstandard-mississippi-wait ( -- )
|
||||
nonstandard-mississippi-duration sleep ;
|
||||
|
||||
: valid-mississippi-count? ( n -- ? )
|
||||
min-mississippi-count max-mississippi-count between? ;
|
||||
|
||||
: announce ( str -- )
|
||||
. flush ;
|
||||
! say-slack ;
|
||||
|
||||
: announce-sip ( sip -- )
|
||||
"%d Mississippi" sprintf announce ;
|
||||
|
||||
: announce-fake-terminal ( terminal -- )
|
||||
number>string random-m-word 2array " " join announce ;
|
||||
|
||||
: announce-random-stupid-word ( -- )
|
||||
random-stupid-word announce ;
|
||||
|
||||
: announce-random-sip ( -- )
|
||||
1000 random announce-sip ;
|
||||
|
||||
: announce-go! ( -- )
|
||||
"GO!" announce ;
|
||||
|
||||
: announce-standard-mississippis ( terminal -- )
|
||||
[1,b] [ standard-mississippi-duration sleep announce-sip ] each ;
|
||||
|
||||
:: announce-nonstandard-mississippi ( terminal sip -- )
|
||||
{
|
||||
{ .3 [ ] }
|
||||
{ .1 [ announce-random-sip ] }
|
||||
{ .075 [ announce-random-stupid-word ] }
|
||||
{ .025 [ terminal announce-fake-terminal ] }
|
||||
{ .5 [ sip announce-sip ] }
|
||||
} casep ;
|
||||
|
||||
: announce-nonstandard-mississippis ( terminal -- )
|
||||
[
|
||||
1 - [ dup <array> ] [ [1,b] ] bi
|
||||
[ nonstandard-mississippi-wait announce-nonstandard-mississippi ] 2each
|
||||
]
|
||||
[ announce-sip ] bi ;
|
||||
|
||||
: announce-mississippis ( terminal standard? -- )
|
||||
[ announce-standard-mississippis ] [ announce-nonstandard-mississippis ] if ;
|
||||
|
||||
: mississippi-go! ( standard? terminal -- )
|
||||
dup valid-mississippi-count?
|
||||
[ announce-go! swap announce-mississippis ]
|
||||
[ 2drop random-no-word announce ] if ;
|
||||
|
||||
: <heartbeat-response> ( -- response )
|
||||
"mississippis" <text-content> ;
|
|
@ -0,0 +1,61 @@
|
|||
! Copyright (C) 2020 .
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel regexp sequences http.server http.server.responses db db.types db.tuples unicode formatting assocs ;
|
||||
USING: bonerbonerboner bonerbonerboner.services.slack ;
|
||||
|
||||
IN: bonerbonerboner.services.platzisms
|
||||
|
||||
TUPLE: platzism id quote ;
|
||||
|
||||
platzism "platzisms"
|
||||
{
|
||||
{ "id" "id" +db-assigned-id+ }
|
||||
{ "quote" "quote" TEXT }
|
||||
} define-persistent
|
||||
|
||||
: ensure-platzisms ( -- )
|
||||
[ platzism ensure-table ] with-bbb-db ;
|
||||
|
||||
: <platzism> ( str -- platzism )
|
||||
[ f ] dip platzism boa ;
|
||||
|
||||
: add-platzism ( str -- )
|
||||
[ <platzism> insert-tuple ] with-bbb-db ;
|
||||
|
||||
: platzism-exists? ( str -- ? )
|
||||
[ >lower "SELECT id FROM platzisms WHERE lower(quote) = '%s'" sprintf sql-query ] with-bbb-db empty? not ;
|
||||
|
||||
: is-platz? ( str -- ? )
|
||||
R/ ^platz\?$/i matches? ;
|
||||
|
||||
: is-platzism? ( str -- ? )
|
||||
R/ ^steve platz is currently .+/i matches? ;
|
||||
|
||||
: random-platzism ( -- platzism )
|
||||
"SELECT quote from platzisms ORDER BY RANDOM() LIMIT 1" [ sql-query ] with-bbb-db
|
||||
dup empty? [ drop "I'm not sure what Platz is up to." ] [ first first ] if ;
|
||||
|
||||
: repost-callout ( -- )
|
||||
"We already know Platz is doing that" say-slack ;
|
||||
|
||||
: confirm-platzism ( -- )
|
||||
"noted" say-slack ;
|
||||
|
||||
: share-platzism ( -- )
|
||||
random-platzism say-slack ;
|
||||
|
||||
: log/confirm-platzism ( str -- )
|
||||
dup platzism-exists?
|
||||
[ drop repost-callout ]
|
||||
[
|
||||
add-platzism
|
||||
confirm-platzism
|
||||
] if ;
|
||||
|
||||
: check-platz ( event -- )
|
||||
"text" of
|
||||
[ is-platz? [ share-platzism ] when ]
|
||||
[ is-platzism? [ log/confirm-platzism ] when* ] bi ;
|
||||
|
||||
[ check-platz ] add-slack-handler
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
! Copyright (C) 2020 .
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
|
||||
USING: kernel fry db db.sqlite environment math.parser ;
|
||||
|
||||
IN: bonerbonerboner.services
|
||||
|
||||
CONSTANT: bbb-default-port 8069
|
||||
|
||||
: with-bbb-db ( quot -- )
|
||||
'[ "bbb.db" <sqlite-db> _ with-db ] call ; inline
|
||||
|
||||
: bbb-api-port ( -- port )
|
||||
"BBB_API_PORT" os-env [ string>number ] [ bbb-default-port ] if* ;
|
|
@ -0,0 +1,64 @@
|
|||
! Copyright (C) 2020 .
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
|
||||
USING: io.sockets.secure kernel http http.server http.server.dispatchers accessors furnace.actions namespaces http.server.responses io.servers io.sockets.secure.debug json.reader assocs combinators sequences arrays threads locals formatting json.writer urls http.client hashtables ;
|
||||
USING: prettyprint ;
|
||||
|
||||
IN: bonerbonerboner.services.slack
|
||||
|
||||
SYMBOLS: slack-callbacks current-slack-webhook-url current-slack-authorization-token ;
|
||||
|
||||
TUPLE: slack < dispatcher ;
|
||||
|
||||
: add-slack-handler ( quot: ( event -- ) -- )
|
||||
slack-callbacks get append slack-callbacks set ;
|
||||
|
||||
: <bad-callback-response> ( -- response )
|
||||
"400" "unrecognized event type" <trivial-response> ;
|
||||
|
||||
: <heartbeat-response> ( -- response )
|
||||
"slack" <text-content> ;
|
||||
|
||||
: <ok-response> ( -- response )
|
||||
"200" "OK" <trivial-response> ;
|
||||
|
||||
: handle-challenge ( json -- response )
|
||||
"challenge" of <text-content> ;
|
||||
|
||||
:: handle-slack-event ( slack-event -- response )
|
||||
"bot_id" slack-event key? "subtype" slack-event key? or
|
||||
[
|
||||
slack-callbacks get length slack-event <array>
|
||||
slack-callbacks get [ curry "Slack Callback" spawn drop ] 2each
|
||||
] unless
|
||||
<ok-response> ;
|
||||
|
||||
: <slack-event-action> ( -- action )
|
||||
<action>
|
||||
[
|
||||
request get post-data>> data>> json> dup
|
||||
"type" of
|
||||
{
|
||||
{ "url_verification" [ handle-challenge ] }
|
||||
{ "event_callback" [ handle-slack-event ] }
|
||||
[ drop <bad-callback-response> ]
|
||||
} case
|
||||
] >>submit ;
|
||||
|
||||
: <heartbeat-action> ( -- action )
|
||||
<action> [ <heartbeat-response> ] >>display ;
|
||||
|
||||
: slack-post-message ( payload -- )
|
||||
>json
|
||||
current-slack-webhook-url get >url
|
||||
<post-request>
|
||||
http-request 2drop ;
|
||||
|
||||
: say-slack ( str -- )
|
||||
"text" associate
|
||||
slack-post-message ;
|
||||
|
||||
: <slack> ( -- responder )
|
||||
slack new-dispatcher
|
||||
<slack-event-action> "slack-events" add-responder
|
||||
<heartbeat-action> "heartbeat" add-responder ;
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version='1.0' ?>
|
||||
<t:chloe xmlns:t="http://factorcode.org/chloe/1.0" >
|
||||
<html class="@theme" >
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-sale=1"/>
|
||||
</head>
|
||||
<body/>
|
||||
</html>
|
||||
</t:chloe>
|
|
@ -0,0 +1,256 @@
|
|||
! Copyright (C) 2020 .
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: kernel math math.parser strings calendar alien.syntax sequences urls http.client formatting json.reader assocs combinators splitting classes.maybe ;
|
||||
USING: prettyprint ;
|
||||
|
||||
IN: nhl
|
||||
|
||||
TUPLE: conference
|
||||
{ id integer }
|
||||
{ name string }
|
||||
{ short-name string }
|
||||
{ abbreviation string } ;
|
||||
|
||||
TUPLE: timezone
|
||||
{ id string }
|
||||
{ offset integer }
|
||||
{ tz string } ;
|
||||
|
||||
TUPLE: venue
|
||||
{ name: string }
|
||||
{ city: string }
|
||||
{ timezone timezone } ;
|
||||
|
||||
TUPLE: division
|
||||
{ id integer }
|
||||
{ name string }
|
||||
! { name-short string }
|
||||
{ abbreviation string }
|
||||
{ conference maybe{ conference } } ;
|
||||
|
||||
TUPLE: franchise
|
||||
{ id integer }
|
||||
{ team-name string }
|
||||
{ first-season-id integer }
|
||||
{ location-name string }
|
||||
{ most-recent-team-id integer } ;
|
||||
|
||||
TUPLE: team
|
||||
{ id integer }
|
||||
{ name string }
|
||||
{ team-name string }
|
||||
{ location-name string }
|
||||
{ short-name string }
|
||||
{ official-site-url url }
|
||||
{ abbreviation string }
|
||||
! { first-year timestamp }
|
||||
{ first-year integer }
|
||||
{ division division }
|
||||
{ franchise franchise }
|
||||
{ venue venue } ;
|
||||
|
||||
TUPLE: game-time
|
||||
{ period integer }
|
||||
{ period-sec integer } ;
|
||||
! { period-sec timestamp } ;
|
||||
|
||||
TUPLE: location
|
||||
{ x integer }
|
||||
{ y integer } ;
|
||||
|
||||
TUPLE: player-position
|
||||
{ code string }
|
||||
{ name string }
|
||||
{ type string }
|
||||
{ abbreviation string } ;
|
||||
|
||||
TUPLE: player
|
||||
{ id integer }
|
||||
{ full-name string }
|
||||
{ first-name string }
|
||||
{ last-name string }
|
||||
{ primary-number string }
|
||||
{ current-team string }
|
||||
{ position player-position }
|
||||
{ height string }
|
||||
{ weight integer }
|
||||
{ shoots/catches string }
|
||||
{ alternate-captain? boolean }
|
||||
{ captain? boolean }
|
||||
{ rookie? boolean }
|
||||
{ nationality string }
|
||||
{ birth-date timestamp }
|
||||
{ birth-city string }
|
||||
{ birth-state/prvince maybe{ string } }
|
||||
{ birth-country string } ;
|
||||
|
||||
TUPLE: status
|
||||
{ abstract-state string }
|
||||
{ coded-state string }
|
||||
{ detailed-state string }
|
||||
{ code string }
|
||||
{ start-time-tbd boolean } ;
|
||||
|
||||
TUPLE: league-record
|
||||
{ wins integer }
|
||||
{ losses integer }
|
||||
{ ot integer }
|
||||
{ type string } ;
|
||||
|
||||
TUPLE: team-info
|
||||
{ scores integer }
|
||||
{ attempts integer }
|
||||
{ goals integer }
|
||||
{ shots-on-goal integer }
|
||||
{ rink-side string }
|
||||
{ goalie-pulled? boolean }
|
||||
{ num-skaters integer }
|
||||
{ power-play? boolean }
|
||||
{ league-record league-record }
|
||||
{ score integer }
|
||||
{ team team } ;
|
||||
|
||||
TUPLE: teams
|
||||
{ }
|
||||
|
||||
TUPLE: game
|
||||
{ id integer }
|
||||
{ link team }
|
||||
{ type team }
|
||||
{ season string }
|
||||
{ date timestamp }
|
||||
{ status status }
|
||||
{ teams teams }
|
||||
{ linescore linescore }
|
||||
{ venue venue }
|
||||
{ content content }
|
||||
{ series-summary series-summary } ;
|
||||
|
||||
TUPLE: event
|
||||
{ game-id integer }
|
||||
{ id integer }
|
||||
{ type string }
|
||||
{ sub-type string }
|
||||
{ time game-time }
|
||||
{ location location }
|
||||
{ team team }
|
||||
{ by sequence }
|
||||
{ on player } ;
|
||||
|
||||
TUPLE: date
|
||||
{ date string }
|
||||
{ total-items integer }
|
||||
{ total-events integer }
|
||||
{ total-games integer }
|
||||
{ total-matches integer }
|
||||
{ games sequence }
|
||||
{ events sequence }
|
||||
{ matches sequence } ;
|
||||
|
||||
TUPLE: schedule
|
||||
{ copyright string }
|
||||
{ total-items integer }
|
||||
{ total-events integer }
|
||||
{ total-games integer }
|
||||
{ total-matches integer }
|
||||
{ wait integer }
|
||||
{ dates sequence } ;
|
||||
|
||||
CONSTANT: nhl-base-url "https://statsapi.web.nhl.com/api/v1/"
|
||||
! TODO: CACHING
|
||||
|
||||
: >entity-url ( entity id -- url )
|
||||
dup string? [ string>number ] when
|
||||
"%s/%d" sprintf nhl-base-url prepend >url ;
|
||||
|
||||
: entity-get ( id entity -- json )
|
||||
swap over [
|
||||
>entity-url http-get nip json>
|
||||
] dip of first ;
|
||||
|
||||
: entities-get ( entity -- seq )
|
||||
dup [
|
||||
nhl-base-url prepend http-get nip json>
|
||||
] dip of ;
|
||||
|
||||
: parse-conference ( json -- conference )
|
||||
"CONF" . dup .
|
||||
{
|
||||
[ "id" of ] [ "name" of ] [ "shortName" of ] [ "abbreviation" of ]
|
||||
} cleave
|
||||
conference boa ;
|
||||
|
||||
: conference-get ( id -- conference ) "conferences" entity-get parse-conference ;
|
||||
: conferences-get ( -- conferences ) "conferences" entities-get [ parse-conference ] map ;
|
||||
|
||||
: parse-division ( json -- division )
|
||||
{
|
||||
[ "id" of ] [ "name" of ] [ "abbreviation" of ]
|
||||
! [ "conference" of ] ! "id" of conference-get ]
|
||||
} cleave
|
||||
f
|
||||
division boa ;
|
||||
|
||||
: parse-franchise ( json -- franchise )
|
||||
{
|
||||
[ "franchiseId" of ] [ "teamName" of ] [ "firstSeasonId" of ]
|
||||
[ "locationName" of ] [ "mostRecentTeamId" of ]
|
||||
} cleave
|
||||
franchise boa ;
|
||||
|
||||
: parse-position ( json -- player-position )
|
||||
{
|
||||
[ "code" of ] [ "name" of ] [ "type" of ] [ "abbreviation" of ]
|
||||
} cleave player-position boa ;
|
||||
|
||||
: parse-player ( json -- player )
|
||||
{
|
||||
[ "id" of ]
|
||||
[ "fullName" of ]
|
||||
[ "firstName" of ]
|
||||
[ "lastName" of ]
|
||||
[ "primaryNumber" of ]
|
||||
[ "currentTeam" of "name" of ]
|
||||
[ "primaryPosition" of parse-position ]
|
||||
[ "height" of ]
|
||||
[ "weight" of ]
|
||||
[ "shootsCatches" of ]
|
||||
[ "alternateCaptain" of ]
|
||||
[ "captain" of ]
|
||||
[ "rookie" of ]
|
||||
[ "nationality" of ]
|
||||
[ "birthDate" of "-" split [ string>number ] map [ first ] [ second ] [ third ] tri <date> ]
|
||||
[ "birthCity" of ]
|
||||
[ "birthStateProvince" of ]
|
||||
[ "birthCountry" of ]
|
||||
} cleave player boa ;
|
||||
|
||||
: division-get ( id -- division )
|
||||
"divisions" entity-get parse-division ;
|
||||
: divisions-get ( -- divisions )
|
||||
"divisions" entities-get [ parse-division ] map ;
|
||||
|
||||
: franchise-get ( id -- division )
|
||||
"franchises" entity-get parse-franchise ;
|
||||
: franchises-get ( -- divisions )
|
||||
"franchises" entities-get [ parse-franchise ] map ;
|
||||
|
||||
: player-get ( id -- player ) "people" entity-get parse-player ;
|
||||
: players-get ( ids -- players ) [ player-get ] map ;
|
||||
|
||||
: parse-timezone ( json -- timezone )
|
||||
[ "id" of ] [ "offset" of ] [ "tz" of ] tri timezone boa ;
|
||||
: parse-venue ( json -- venue )
|
||||
[ "name" of ] [ "city" of ] [ "timeZone" of parse-timezone ] tri venue boa ;
|
||||
|
||||
: parse-team ( json -- team )
|
||||
{
|
||||
[ "id" of ] [ "name" of ] [ "teamName" of ] [ "locationName" of ]
|
||||
[ "shortName" of ] [ "officialSiteUrl" of >url ] [ "abbreviation" of ]
|
||||
[ "firstYearOfPlay" of string>number ] [ "division" of "id" of division-get ]
|
||||
[ "franchiseId" of franchise-get ] [ "venue" of parse-venue ]
|
||||
} cleave
|
||||
team boa ;
|
||||
|
||||
: team-get ( id -- team ) "teams" entity-get parse-team ;
|
||||
: teams-get ( -- teams ) "teams" entities-get [ parse-team ] map ;
|
Loading…
Reference in New Issue