Moontalk server and client (provided by many parties)
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

197 lignes
5.0KB

  1. #!/usr/bin/wish
  2. # Default values.
  3. set host "7ks473deh6ggtwqsvbqdurepv5i6iblpbkx33b6cydon3ajph73sssad.onion"
  4. set port "50000"
  5. set username "anonymous"
  6. set reconnect_max_tries -1
  7. set reconnect_time 10000
  8. set notification_exe "/usr/bin/aplay"
  9. set notification_file "./notification.wav"
  10. set notification_delay 1000
  11. # Don't touch these
  12. set identity "Anon ?"
  13. set reconnect_try 0
  14. set sock 0
  15. set notification_cooldown 0
  16. proc window_visibility {w val} {
  17. if {$val} {
  18. wm deiconify $w
  19. } else {
  20. wm withdraw $w
  21. }
  22. }
  23. proc on_user_connect {w} {
  24. global reconnect_try
  25. set reconnect_try 0
  26. window_visibility . true
  27. socket_connect
  28. window_visibility $w false
  29. }
  30. proc display_connect_dialog {} {
  31. global reconnect_try
  32. global host
  33. global port
  34. set w .wconnect
  35. if { [winfo exists $w] } {
  36. window_visibility $w true
  37. focus $w
  38. } else {
  39. toplevel $w
  40. wm title $w "MoonTk - Connect to MoonTalk"
  41. set callback_wrapper "on_user_connect $w"
  42. pack [label $w.lh -text "Host:"] -anchor w
  43. pack [entry $w.eh -textvariable host] -fill x
  44. pack [label $w.lp -text "Port:"] -anchor w
  45. pack [entry $w.ep -textvariable port] -fill x
  46. pack [button $w.bc -text "connect" -command $callback_wrapper]
  47. bind $w.eh <Return> $callback_wrapper
  48. bind $w.eh <KP_Enter> $callback_wrapper
  49. bind $w.ep <Return> $callback_wrapper
  50. bind $w.ep <KP_Enter> $callback_wrapper
  51. focus $w
  52. }
  53. }
  54. wm title . "MoonTk"
  55. pack [entry .input] -side bottom -fill x
  56. pack [scrollbar .sy -command {.messages yview}] -side right -fill y
  57. pack [text .messages -wrap none -xscrollcommand {.sx set} -yscrollcommand {.sy set}] -fill both -expand 1
  58. pack [scrollbar .sx -orient horizontal -command {.messages xview}] -fill x
  59. proc socket_connect {} {
  60. global sock
  61. global host
  62. global port
  63. append_message "Connecting to $host:$port..."
  64. if {[catch {socket -async $host $port} sock]} {
  65. on_socket_connection_failed
  66. } else {
  67. fconfigure $sock -blocking false
  68. fconfigure $sock -translation binary
  69. fileevent $sock readable on_socket_receive
  70. fileevent $sock writable on_socket_connect
  71. }
  72. }
  73. proc on_socket_connect {} {
  74. global reconnect_try
  75. global sock
  76. set error [fconfigure $sock -error]
  77. if {$error ne ""} {
  78. catch {close $sock}
  79. on_socket_connection_failed
  80. return
  81. }
  82. append_message "Successfully connected to the server."
  83. fileevent $sock writable {}
  84. set reconnect_try 0
  85. }
  86. proc on_socket_connection_failed {} {
  87. global reconnect_time
  88. global reconnect_max_tries
  89. global reconnect_try
  90. if { $reconnect_max_tries != -1
  91. && $reconnect_try >= $reconnect_max_tries } {
  92. tk_messageBox -message "Maximum reconnect tries reached." -type ok
  93. display_connect_dialog
  94. } else {
  95. set reconnect_try [expr {$reconnect_try + 1}]
  96. append_message "Failed to connect to the server, retrying in [expr {$reconnect_time/1000}] seconds."
  97. after $reconnect_time socket_connect
  98. }
  99. }
  100. proc on_socket_disconnect {} {
  101. append_message "Disconnected from server..."
  102. socket_connect
  103. }
  104. proc parse_identity {data} {
  105. global identity
  106. regexp -all {^Server: You are now known as \"(.+)\"\.} $data whole_match ident
  107. if {[info exists ident]} {
  108. set identity $ident
  109. }
  110. }
  111. proc reset_notification {} {
  112. global notification_cooldown
  113. set notification_cooldown 0
  114. }
  115. proc play_notification {} {
  116. global notification_exe
  117. global notification_file
  118. global notification_cooldown
  119. global notification_delay
  120. set notification_cooldown 1
  121. exec $notification_exe $notification_file "&"
  122. after $notification_delay reset_notification
  123. }
  124. proc on_socket_receive {} {
  125. global sock
  126. global identity
  127. global notification_cooldown
  128. set error [fconfigure $sock -error]
  129. # catch gets = read error
  130. # eof = other side disconnected
  131. if { $error ne ""
  132. || [catch {gets $sock} data]
  133. || [eof $sock]} {
  134. catch {close $sock}
  135. on_socket_disconnect
  136. return
  137. }
  138. if {[string match "Server: *" $data]} {
  139. parse_identity $data
  140. }
  141. if { !$notification_cooldown } {
  142. play_notification
  143. }
  144. append_message $data
  145. }
  146. proc send_message {msg} {
  147. global sock
  148. global identity
  149. set formatted_msg [format_message $msg]
  150. puts $sock $formatted_msg
  151. flush $sock
  152. append_message "$identity: $formatted_msg"
  153. }
  154. proc timestamp {} {
  155. return [clock format [clock seconds] -gmt true -format {%Y/%m/%d %H:%M:XX}]
  156. }
  157. proc format_message {msg} {
  158. global username
  159. set ts [timestamp]
  160. if {[string match "/*" $msg]} {
  161. return $msg
  162. } else {
  163. return "<$ts $username> $msg"
  164. }
  165. }
  166. proc append_message {msg} {
  167. .messages insert end "$msg\n"
  168. .messages see end
  169. }
  170. proc user_enter {} {
  171. send_message [.input get]
  172. .input delete 0 end
  173. }
  174. bind .input <Return> user_enter
  175. bind .input <KP_Enter> user_enter
  176. window_visibility . false
  177. display_connect_dialog