Add example client.
authorDavid Thompson <dthompson2@worcester.edu>
Mon, 14 Jul 2014 01:32:16 +0000 (21:32 -0400)
committerDavid Thompson <dthompson2@worcester.edu>
Mon, 14 Jul 2014 01:32:16 +0000 (21:32 -0400)
* .gitignore: Ignore examples/tox_save
* README.md: Add instructions for using example client.
* examples/client.scm: New file.
* examples/guile-tox.sample: New file.

.gitignore
README.md
examples/client.scm [new file with mode: 0644]
examples/guile-tox.sample [new file with mode: 0644]

index 15a8561..2e68582 100644 (file)
@@ -10,3 +10,4 @@
 /config.status
 /configure
 /env
+/examples/tox_save
index c7995db..04d547e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -38,6 +38,27 @@ To use the low-level API:
 (tox-kill tox)
 ```
 
+Example Client
+--------------
+
+An example client is included in the guile-toxcore distribution.  Unlike
+guile-toxcore, the example client requires Guile version 2.0.11 or greater.
+
+To run the client:
+
+```
+cd examples
+cp guile-tox.sample ~/.guile-tox # Copy sample config
+guile -L .. client.scm
+```
+
+The client does not accept input directly.  In order to give commands, you
+must connect to the REPL server via telnet or use the geiser package in Emacs.
+
+```
+telnet localhost 37146
+```
+
 Dependencies
 ------------
 
diff --git a/examples/client.scm b/examples/client.scm
new file mode 100644 (file)
index 0000000..9e6afbd
--- /dev/null
@@ -0,0 +1,90 @@
+(use-modules (system repl coop-server)
+             (system repl server)
+             (tox))
+
+(define tox (make-tox))
+
+(define tox-bootstrap-nodes '())
+(define tox-repl-port 37146)
+
+(define (bootstrap!)
+  (if (null? tox-bootstrap-nodes)
+      (error "No bootstrap nodes!  Please configure tox-bootstrap-nodes.")
+      (for-each (lambda (node)
+                  (tox-bootstrap-from-address
+                   tox
+                   (assq-ref node 'ip)
+                   (assq-ref node 'ipv6?)
+                   (assq-ref node 'port)
+                   (tox-client-id (assq-ref node 'id))))
+                tox-bootstrap-nodes)))
+
+(define (quit!)
+  (abort-to-prompt 'tox-client))
+
+(define (save!)
+  (display "Saving to tox_save\n")
+  (with-output-to-file "tox_save"
+    (lambda ()
+      (format #t "~a" (tox-save tox)))))
+
+(define (load!)
+  (display "Loading tox_save\n")
+  (tox-load tox (with-input-from-file "tox_save" read)))
+
+(define connected? #f)
+(define last-connection-attempt (current-time))
+(define connection-retry-interval 3)
+
+;; Load user init file
+(let ((config-file (string-append (getenv "HOME") "/.guile-tox")))
+  (if (file-exists? config-file)
+      (load config-file)
+      (error (format #f "No .guile-tox file found in ~a" (getenv "HOME")))))
+
+;; Boot REPL server
+(define repl
+  (spawn-coop-repl-server
+   (make-tcp-server-socket #:port tox-repl-port)))
+
+(format #t "Welcome to Guile-Tox!
+This client acts a server to send commands to via the Guile REPL.
+Connect to the REPL server via telnet or Emacs on port ~a
+Once you've connected to the REPL, try setting your nickname by typing:
+  (set-tox-name \"Tox User\")
+To discover other Tox procedures, type:
+  ,a tox
+To see the documentation for a procedure, type:
+  ,d <procedure-name-goes-here>
+Happy hacking!\n\n"
+        tox-repl-port)
+(load!)
+(bootstrap!)
+
+(call-with-prompt
+ 'tox-client
+ (lambda ()
+   (while #t
+     (when (not connected?)
+       (if (tox-connected? tox)
+           (begin
+             (display "Connected to DHT\n")
+             (set! connected? #t))
+           (let ((time (current-time)))
+             (when (> time
+                      (+ last-connection-attempt
+                         connection-retry-interval))
+               (display "Re-trying connection...\n")
+               (set! last-connection-attempt time)
+               (bootstrap!)))))
+
+     (poll-coop-repl-server repl)
+     (tox-do tox)
+     (usleep (* (tox-do-interval tox) 1000))))
+ (lambda args
+   (display "Bye!\n")
+   (save!)))
+
+;; Local Variables:
+;; compile-command: "guile -L .. client.scm"
+;; End:
diff --git a/examples/guile-tox.sample b/examples/guile-tox.sample
new file mode 100644 (file)
index 0000000..6cef161
--- /dev/null
@@ -0,0 +1,56 @@
+(use-modules (tox util))
+
+(define tox-bootstrap-nodes
+  '(((ip . "192.254.75.98")
+     (id . "951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F")
+     (port . 33445)
+     (ipv6? . #t))
+    ((ip . "144.76.60.215")
+     (id . "04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F")
+     (port . 33445)
+     (ipv6? . #t))
+    ((ip . "23.226.230.47")
+     (id . "A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074")
+     (port . 33445)
+     (ipv6? . #t))
+    ((ip . "37.187.20.216")
+     (id . "4FD54CFD426A338399767E56FD0F44F5E35FA8C38C8E87C8DC3FEAC0160F8E17")
+     (port . 33445)
+     (ipv6? . #t))
+    ((ip . "54.199.139.199")
+     (id . "7F9C31FE850E97CEFD4C4591DF93FC757C7C12549DDD55F8EEAECC34FE76C029")
+     (port . 33445)
+     (ipv6? . #f))
+    ((ip . "37.59.102.176")
+     (id . "B98A2CEAA6C6A2FADC2C3632D284318B60FE5375CCB41EFA081AB67F500C1B0B")
+     (port . 33445)
+     (ipv6? . #t))
+    ((ip . "192.210.149.121")
+     (id . "F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67")
+     (port . 33445)
+     (ipv6? . #f))
+    ((ip . "37.187.46.132")
+     (id . "5EB67C51D3FF5A9D528D242B669036ED2A30F8A60E674C45E7D43010CB2E1331")
+     (port . 33445)
+     (ipv6? . #t))))
+
+(define (tox-friend-names tox)
+  (map (lambda (friend-number)
+         (tox-friend-name tox friend-number))
+       (tox-friend-list tox)))
+
+(add-hook! (tox-friend-request-hook tox)
+           (lambda (tox public-key message)
+             (format #t
+                     "Auto-accept friend request:\nClient ID: ~a\nMessage: ~a\n\n"
+                     (bytevector->hex-string public-key)
+                     message)
+             (tox-add-friend-no-request tox public-key)))
+
+(add-hook! (tox-message-hook tox)
+           (lambda (tox friend-number message)
+             ;; Easy way to kill the client for testing purposes.
+             (when (string=? message "quit")
+               (quit!))
+             (let ((name (tox-friend-name tox friend-number)))
+               (format #t "~a: ~a\n" name message))))