2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  streaming  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"net/http" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-19 09:47:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"codeberg.org/gruf/go-kv" 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/api" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/gtserror" 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-19 09:47:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/superseriousbusiness/gotosocial/internal/log" 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/gin-gonic/gin" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/gorilla/websocket" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var  wsUpgrader  =  websocket . Upgrader {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ReadBufferSize :   1024 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									WriteBufferSize :  1024 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// we expect cors requests (via eg., pinafore.social) so be lenient 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									CheckOrigin :  func ( r  * http . Request )  bool  {  return  true  } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-02 19:06:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// StreamGETHandler swagger:operation GET /api/v1/streaming streamGet  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Initiate a websocket connection for live streaming of statuses and notifications.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// The scheme used should *always* be `wss`. The streaming basepath can be viewed at `/api/v1/instance`.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// On a successful connection, a code `101` will be returned, which indicates that the connection is being upgraded to a secure websocket connection.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// As long as the connection is open, various message types will be streamed into it.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// GoToSocial will ping the connection every 30 seconds to check whether the client is still receiving.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// If the ping fails, or something else goes wrong during transmission, then the connection will be dropped, and the client will be expected to start it again.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
									
										
										
										
											2022-09-28 18:30:40 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								//	---  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	tags:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	- streaming  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	produces:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	- application/json  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	schemes:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	- wss  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	parameters:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	-  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		name: access_token  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		type: string  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		description: Access token for the requesting account.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		in: query  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		required: true  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	-  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		name: stream  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		type: string  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		description: |-  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			Type of stream to request.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			Options are:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			`user`: receive updates for the account's home timeline.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			`public`: receive updates for the public timeline.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			`public:local`: receive updates for the local timeline.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			`hashtag`: receive updates for a given hashtag.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			`hashtag:local`: receive local updates for a given hashtag.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			`list`: receive updates for a certain list of accounts.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			`direct`: receive updates for direct messages.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		in: query  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		required: true  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	security:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	- OAuth2 Bearer:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		- read:streaming  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//	responses:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		'101':  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			schema:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//				type: object  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//				properties:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//					stream:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						type: array  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						items:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							type: string  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							enum:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							- user  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							- public  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							- public:local  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							- hashtag  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							- hashtag:local  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							- list  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							- direct  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//					event:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						description: |-  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							The type of event being received.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							`update`: a new status has been received.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							`notification`: a new notification has been received.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							`delete`: a status has been deleted.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							`filters_changed`: not implemented.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						type: string  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						enum:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						- update  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						- notification  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						- delete  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						- filters_changed  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//					payload:  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						description: |-  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							The payload of the streamed message.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							Different depending on the `event` type.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							If present, it should be parsed as a string.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							If `event` = `update`, then the payload will be a JSON string of a status.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							If `event` = `notification`, then the payload will be a JSON string of a notification.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//							If `event` = `delete`, then the payload will be a status ID.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						type: string  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//						example: "{\"id\":\"01FC3TZ5CFG6H65GCKCJRKA669\",\"created_at\":\"2021-08-02T16:25:52Z\",\"sensitive\":false,\"spoiler_text\":\"\",\"visibility\":\"public\",\"language\":\"en\",\"uri\":\"https://gts.superseriousbusiness.org/users/dumpsterqueer/statuses/01FC3TZ5CFG6H65GCKCJRKA669\",\"url\":\"https://gts.superseriousbusiness.org/@dumpsterqueer/statuses/01FC3TZ5CFG6H65GCKCJRKA669\",\"replies_count\":0,\"reblogs_count\":0,\"favourites_count\":0,\"favourited\":false,\"reblogged\":false,\"muted\":false,\"bookmarked\":fals…//gts.superseriousbusiness.org/fileserver/01JNN207W98SGG3CBJ76R5MVDN/header/original/019036W043D8FXPJKSKCX7G965.png\",\"header_static\":\"https://gts.superseriousbusiness.org/fileserver/01JNN207W98SGG3CBJ76R5MVDN/header/small/019036W043D8FXPJKSKCX7G965.png\",\"followers_count\":33,\"following_count\":28,\"statuses_count\":126,\"last_status_at\":\"2021-08-02T16:25:52Z\",\"emojis\":[],\"fields\":[]},\"media_attachments\":[],\"mentions\":[],\"tags\":[],\"emojis\":[],\"card\":null,\"poll\":null,\"text\":\"a\"}"  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		'401':  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			description: unauthorized  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//		'400':  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								//			description: bad request  
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( m  * Module )  StreamGETHandler ( c  * gin . Context )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									streamType  :=  c . Query ( StreamQueryKey ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  streamType  ==  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "no stream type provided under query key %s" ,  StreamQueryKey ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										api . ErrorHandler ( c ,  gtserror . NewErrorBadRequest ( err ,  err . Error ( ) ) ,  m . processor . InstanceGet ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									accessToken  :=  c . Query ( AccessTokenQueryKey ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  accessToken  ==  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										err  :=  fmt . Errorf ( "no access token provided under query key %s" ,  AccessTokenQueryKey ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										api . ErrorHandler ( c ,  gtserror . NewErrorUnauthorized ( err ,  err . Error ( ) ) ,  m . processor . InstanceGet ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									account ,  errWithCode  :=  m . processor . AuthorizeStreamingRequest ( c . Request . Context ( ) ,  accessToken ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  errWithCode  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										api . ErrorHandler ( c ,  errWithCode ,  m . processor . InstanceGet ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									stream ,  errWithCode  :=  m . processor . OpenStreamForAccount ( c . Request . Context ( ) ,  account ,  streamType ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  errWithCode  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										api . ErrorHandler ( c ,  errWithCode ,  m . processor . InstanceGet ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-19 09:47:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									l  :=  log . WithFields ( kv . Fields { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ "account" ,  account . Username } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ "path" ,  BasePath } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ "streamID" ,  stream . ID } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										{ "streamType" ,  streamType } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ... ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									wsConn ,  err  :=  wsUpgrader . Upgrade ( c . Writer ,  c . Request ,  nil ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										// If the upgrade fails, then Upgrade replies to the client with an HTTP error response. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// Because websocket issues are a pretty common source of headaches, we should also log 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// this at Error to make this plenty visible and help admins out a bit. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										l . Errorf ( "error upgrading websocket connection: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										close ( stream . Hangup ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									defer  func ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										// cleanup 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										wsConn . Close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										close ( stream . Hangup ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									streamTicker  :=  time . NewTicker ( 30  *  time . Second ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// We want to stay in the loop as long as possible while the client is connected. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// The only thing that should break the loop is if the client leaves or the connection becomes unhealthy. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// If the loop does break, we expect the client to reattempt connection, so it's cheap to leave + try again 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								wsLoop :  
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									for  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										select  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  m  :=  <- stream . Messages : 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-11 16:22:21 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											l . Trace ( "received message from stream" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  :=  wsConn . WriteJSON ( m ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												l . Debugf ( "error writing json to websocket connection; breaking off: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break  wsLoop 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-11 16:22:21 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											l . Trace ( "wrote message into websocket connection" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										case  <- streamTicker . C : 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-11 16:22:21 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											l . Trace ( "received TICK from ticker" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-08 20:38:03 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											if  err  :=  wsConn . WriteMessage ( websocket . PingMessage ,  [ ] byte ( ": ping" ) ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												l . Debugf ( "error writing ping to websocket connection; breaking off: %s" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												break  wsLoop 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-11 16:22:21 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
											l . Trace ( "wrote ping message into websocket connection" ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-19 11:18:55 +02:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}