Moontalk server and client (provided by many parties)
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

197 wiersze
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