copy output to] output: decode-xml output ; if an error, remove part of the error string and parse out the help page if find output "*** ERROR" [ replace output "try do either either either -apply-" "" parse html [thru {> " trim expression newline " " output ] ?? expression ] was-about-users: [ earl [https://github.com/earl 1:00] graham [https://github.com/gchiu/ 13:00] ladislav [https://github.com/ladislav 1:00] rgchris [http://reb4.me/ none] hostilefork [http://hostilefork.com/ -5:00] brianH [https://github.com/BrianHawley -5:00] dockimbel [https://github.com/dockimbel 1:00] cyphre [https://github.com/cyphre 1:00] ] either exists? notable-persons-file [ about-users: load notable-persons-file ; check for old style file if url! = type? about-users/2 [ use [tmp tz rec] [ tmp: copy about-users clear head about-users foreach [user url] tmp [ append about-users user tz: either rec: select was-about-users user [ rec/2 ] [none] repend/only about-users [url tz] ] save notable-persons-file about-users ] ] ] [ about-users: copy was-about-users ] ;; -- compile a list of known people either not exists? visitors-file [ visitors: copy [] foreach [user data] about-users [ append visitors form user ] save visitors-file visitors ] [ visitors: load visitors-file ] ; pass the message to delete ; delete-url: [ so-chat-url 'messages "/" (message-id) 'delete ] delete-message: func [parent-id message-id /silent /local result mess ] [ mess: rejoin compose copy delete-url ?? mess result: to string! write mess: rejoin compose copy delete-url compose/deep copy/deep [ POST [(header)] (rejoin ["fkey=" bot-fkey]) ] if not silent [ switch/default result [ {"It is too late to delete this message"} [reply message-id ["sorry, it's too late to do this now. Be quicker next time"]] {"ok"} [reply message-id ["done"]] ] [ reply message-id ["SO says: " result] ] ] ] add-user-details: func [message-id person user-url timezone [time! none!] /local rec ] [ attempt [ person: to word! person if rec: find about-users person [ remove/part rec 2 ] repend about-users person repend/only about-users [user-url timezone] save notable-persons-file about-users reply message-id ajoin ["Added " person "'s details"] ] ] ; silent is used by the forever loop to update the users online who-is-online: func [message-id /silent /local out page username userid len newbies addressees ] [ addressees: copy "" len: length? visitors out: copy [] newbies: copy [] page: to string! read html-url parse page [ some [ thru "chat.sidebar.loadUser(" copy userid some id-rule thru {("} copy username to {")} (trim/all username username: decode-xml username append out username if not find visitors username [ append visitors username append newbies username ] ) ] to end ] either empty? out [ reply message-id "can not parse the page for users" ] [ either not silent [ reply message-id form out ] [ ; silent scan has detected new users - so let's greet them if not empty? newbies [ foreach person newbies [ append addressees ajoin ["@" person " "] ] speak ajoin [addressees " " greet-message] ] ] if len < length? visitors [ save visitors-file visitors ] ] ] show-all-users: func [message-id /local tmp ] [ tmp: copy [] foreach [user address] about-users [ append tmp user ] reply message-id join "I know something of the following people: " form sort tmp ] ; person is the one asking the question show-user-page: func [message-id user person /local data known timezone gmt err] [ gmt: now gmt/zone: 0:00 gmt: gmt - now/zone known: false user: to string! user attempt [trim/all person known: find about-users to word! person] if #"?" = last user [remove back tail user] if error? set/any 'err try [ either data: select about-users to word! user [ reply message-id ajoin [ "I know this about [" user "](" data/1 ") and their local time is " either time? timezone: data/2 [gmt + timezone] [ "unknown." ] ] ] [ reply message-id ["Sorry, I don't know anything about " user " yet."] ] if not known [ reply message-id ["I'd like to know about you! Use the 'save my details' command"] ] ] [ probe err ] ] ; find-in-links message-id form findstring find-in-links: func [message-id findstring /local out used link ] [ either 3 > length? findstring [ reply message-id "Find string needs to be at least 3 characters" ] [ out: copy "" used: copy [] foreach [key data] bot-expressions [ if all [ not find used data/2 find data/1 findstring ] [ link: ajoin ["[" data/1 "](" data/2 "); "] either chat-length-limit < add length? out length? link [ reply message-id out wait 2 out: copy link ] [ append out link ] append used data/2 ] ] if empty? out [out: copy "nothing found"] reply message-id out ] ] ; SO chat has a 500 character limit for messages with active links ; so let's send in 500 ( chat-length-limit ) char chunks ; this should be a refinement of show-similar-links show-all-links: func [message-id /local out link used] [ out: copy "" used: copy [] foreach [key data] bot-expressions [ if not find used data/2 [ link: ajoin ["[" data/1 "](" data/2 "); "] either chat-length-limit < add length? out length? link [ ; over chat-length-limit so send what we have reply message-id out wait 2 out: copy link ] [append out link] append used data/2 ] ] wait 2 if empty? out [out: copy "nothing found"] reply message-id out ] show-similar-links: func [message-id links /local out link tot used] [ print "in the simlar links function now" out: copy "" used: copy [] foreach [key data] bot-expressions [ if not find used data/2 [ if find/part data/2 links length? links [ link: ajoin ["[" data/1 "](" data/2 "); "] ; if adding a new link exceeds allowed, then send current either chat-length-limit < tot: add length? out length? link [ reply message-id out wait 2 ; and reset out to the new link out: copy link ] [ append out link ] append used data/2 ] ] ] wait 2 ;?? out if empty? out [out: copy "nothing found"] reply message-id out ] reply-time: func [message-id] [ reply message-id to-idate now ] process-dialect: funct [message-id person person-id expression ] [ show-rule: [ 'show any ['me | 'all] [ 'links (show-urls: true) opt ['like set links url! (similar: true)] | 'your 'youtube 'videos (youtube: true) ] ] whois-rule: [ [some ['who 'is | 'whois | 'who 'the 'dickens 'is] copy user to end ] (if found? user [show-user-page message-id user/1 person] done: true) ] whom-rule: ['whom 'do 'you ['know | 'know?] (show-all-users message-id done: true)] save-rule: [ (print "save rule" trim/all person ) 'save 'my 'details set user-url url! ( ?? user-url add-user-details message-id person user-url none done: true ) set user-timezone time! ( add-user-details message-id person user-url user-timezone ) ] save-key-rule: ['save copy expression to end (done: true save-key message-id expression)] do-rule: ['do copy expression to end (done: true attempt [ evaluate-expression message-id mold/only expression ] ) ] do2-rule: [['do/2 | 'do/rebol2] copy expression to end (done: true attempt [ evaluate-expression/r2 message-id mold/only expression ] ) ] do-boron-rule: ['do/boron copy expression to end (done: true attempt [ evaluate-expression/boron message-id mold/only expression ] ) ] do-red-rule: ['do/red copy expression to end (done: true attempt [ evaluate-expression/red message-id mold/only expression ] ) ] do-ideone-rule: ['do/ideone [set language word! | set language string! | set language integer!] copy expression to end (done: true attempt [ probe mold/only expression evaluate-by-ideone message-id ideone-user ideone-pass mold/only expression language "" ] ) ] version-rule: [ 'version (done: true reply message-id ajoin [system/script/header/version " " last system/script/header/date]) ] help-rule: ['help (done: true provide-help message-id)] key-rule: ['keys (done: true show-keys message-id)] remove-key-rule: [; remove-key message-id person person-id expression privileged-users 'remove copy expression to end ( done: true ?? message-id ?? person ?? person-id ?? expression remove-key message-id person person-id form expression privileged-users ) ] greet-rule: [copy greeting ['hello | 'goodbye | 'morning] (reply message-id [greeting " to you too"] done: true)] default-rule: [ ; default .. checks for a word and sends it to the check-keys [set search-key word! | set search-key string!] opt ['for set recipient word!] ( done: true ?? search-key ?? recipient either found? recipient [ recipient: ajoin ["@" recipient] ] [ recipient: copy "" ] process-key-search message-id trim ajoin [search-key " " recipient] ) ] search-key-rule: [ '? default-rule ] delete-rule: [ 'delete (done: true silent: false) opt [copy silent word!] ( either all [block? silent silent/1 = 'silent] [ delete-message/silent parent-id message-id ] [ print "not calling silent" delete-message parent-id message-id ] ) ] time-rule: [ 'what 'is 'the ['time | 'time?] opt ['now? | 'now | 'in 'GMT] (done: true reply-time message-id) ] life-rule: [ 'what 'is 'the 'meaning 'of ['life | 'life?] (done: true reply message-id "42" ) ] show-links-by-rule: [ opt 'show opt 'me opt 'recent 'links ['by | 'from] [set username word! | set username string!] ( done: true find-links-by message-id max-scan-messages username ) ] private-session-rule: [ 'private 'session 'in set private-room integer! ( done: true attempt [ reply message-id "OK, coming" wait 2 speak-private "hello" private-room ] ) ] find-rule: [ 'find [set findstring string! | set findstring word!] ( done: true find-in-links message-id form findstring ) ] who-is-online-rule: [ ['present | 'present?] ( done: true who-is-online message-id ) ] read-raw-rule: [ 'read 'raw set target url! ( done: true raw-read message-id target ) ] dialect-rule: [ ( recipient: none ) show-links-by-rule | show-rule | whois-rule | whom-rule | save-rule | save-key-rule | search-key-rule | do-rule | do2-rule | do-boron-rule | do-red-rule | do-ideone-rule | version-rule | help-rule | key-rule | remove-key-rule | greet-rule | delete-rule | time-rule | life-rule | private-session-rule | find-rule | who-is-online-rule | read-raw-rule | default-rule ] show-urls: similar: links: youtube: done: false tmp: copy "" if error? err: try [ ; what to do about illegal rebol values eg @Graham if error? err2: try [ to block! expression ] [ if find mold err2 {arg1: "email"} [ replace/all expression "@" "" ] ] parse expression: to block! expression dialect-rule ;?? expression ;?? similar ;?? show-urls case [ similar [ show-similar-links message-id links ] show-urls [ show-all-links message-id ] youtube [ show-similar-links message-id https://www.youtube.com wait 2 show-similar-links message-id http://www.youtube.com ] done [] ; true [ reply message-id [ "Sorry, don't understand " expression ]] ; replace by using Eliza true [ reply message-id eliza/match mold expression ] ] ] [ ; sends error ; reply message-id mold err ; now uses Eliza reply message-id eliza/match mold expression ] ] process-bot-cmd: func [person person-id message-id cmd expression] [ switch/default cmd [ "?" "h" [provide-help message-id] "d" [process-dialect message-id person person-id expression] "k" [show-keys message-id] "rm" [remove-key message-id person person-id expression privileged-users] "s" [save-key message-id expression] "v" [reply message-id form system/script/header/version] "x" [attempt [evaluate-expression message-id expression]] ] [ ; unknown command - object ; reply message-id [ cmd " is not in my repertoire yet." ] reply message-id eliza/match mold expression ] ] process-key-search: func [message-id expression /local understood search-key person ] [ understood: false set [search-key person] parse expression none unless all [ person parse person ["@" to end] ] [person: none] ; remove punctuation of ! and ? if find [#"!" #"?"] last search-key [remove back tail search-key] foreach [key data] bot-expressions [ if find/part key search-key length? search-key [ understood: true reply message-id ["[" data/1 "](" data/2 ") " either found? person [person] [""]] break ] ] if not understood [ ;reply message-id [ {sorry "} expression {" is not in my current repertoire. Try /h for help} ] reply message-id eliza/match mold expression ] ] ; cmd is k, rm, s etc, and expression is either "" or something like "print 1 + 2" bot-cmd-rule: [ botname some space [ "/" copy cmd some non-space [ end (expression: copy "") | some space copy expression to end (trim expression) ] ( process-bot-cmd user-name person-id message-id cmd expression) | ; some keyword or dialected command follows copy key to end ( ; process-key-search message-id trim key process-dialect message-id user-name person-id key ) ] ] message-rule: [