// CertificateLockFile adds a new certificate lock on the given Client and // Config that ensures that a server's certificate is signed by the same CA // from connection-to-connection. This is helpful when connecting to servers // with self-signed certificates. // // If filename does not exist, the server's certificate chain will be written // to that file. If it does exist, certificates will be read from that file and // added to RootCAs in config's TLSConfig. // // Example: // // if firstConnectionToServer { // // Allow self-signed certificates to be accepted on the initial // // connection. // config.TLSConfig.InsecureSkipVerify = true // } // gumbleutil.CertificateLockFile(client, &config, filename) // // if err := client.Connect(); err != nil { // panic(err) // } func CertificateLockFile(client *gumble.Client, config *gumble.Config, filename string) (gumble.Detacher, error) { if file, err := os.Open(filename); err == nil { defer file.Close() if config.TLSConfig.RootCAs == nil { config.TLSConfig.RootCAs = x509.NewCertPool() } if data, err := ioutil.ReadAll(file); err == nil { config.TLSConfig.RootCAs.AppendCertsFromPEM(data) } return nil, nil } return client.Attach(Listener{ Connect: func(e *gumble.ConnectEvent) { tlsClient, ok := e.Client.Conn().(*tls.Conn) if !ok { return } serverCerts := tlsClient.ConnectionState().PeerCertificates file, err := os.Create(filename) if err != nil { return } block := pem.Block{ Type: "CERTIFICATE", } for _, cert := range serverCerts { block.Bytes = cert.Raw pem.Encode(file, &block) } file.Close() }, }), nil }
func fetchYoutubeInfo(client *gumble.Client, id string) { var info videoInfo // Fetch + parse video info url := fmt.Sprintf("http://gdata.youtube.com/feeds/api/videos/%s?v=2&alt=jsonc", id) if resp, err := http.Get(url); err != nil { return } else { decoder := json.NewDecoder(resp.Body) if err := decoder.Decode(&info); err != nil { return } info.Data.Duration *= time.Second resp.Body.Close() } // Create response string var buffer bytes.Buffer if err := outputTemplate.Execute(&buffer, info); err != nil { return } message := gumble.TextMessage{ Channels: []*gumble.Channel{ client.Self.Channel, }, Message: buffer.String(), } client.Send(&message) }
// UserGroups fetches the group names the given user belongs to in the given // channel. The slice of group names sent via the returned channel. On error, // the returned channel is closed without without sending a slice. func UserGroups(client *gumble.Client, user *gumble.User, channel *gumble.Channel) <-chan []string { ch := make(chan []string) if !user.IsRegistered() { close(ch) return ch } var detacher gumble.Detacher listener := Listener{ Disconnect: func(e *gumble.DisconnectEvent) { detacher.Detach() close(ch) }, ChannelChange: func(e *gumble.ChannelChangeEvent) { if e.Channel == channel && e.Type.Has(gumble.ChannelChangeRemoved) { detacher.Detach() close(ch) } }, PermissionDenied: func(e *gumble.PermissionDeniedEvent) { if e.Channel == channel && e.Type == gumble.PermissionDeniedPermission && (e.Permission&gumble.PermissionWrite) != 0 { detacher.Detach() close(ch) } }, ACL: func(e *gumble.ACLEvent) { if e.ACL.Channel != channel { return } var names []string for _, g := range e.ACL.Groups { if (g.UsersAdd[user.UserID] != nil || g.UsersInherited[user.UserID] != nil) && g.UsersRemove[user.UserID] == nil { names = append(names, g.Name) } } detacher.Detach() ch <- names close(ch) }, } detacher = client.Attach(&listener) channel.RequestACL() return ch }
func New(client *gumble.Client) (*Stream, error) { s := &Stream{ client: client, userStreams: make(map[uint32]openal.Source), sourceFrameSize: client.Config.GetAudioFrameSize(), } s.deviceSource = openal.CaptureOpenDevice("", gumble.AudioSampleRate, openal.FormatMono16, uint32(s.sourceFrameSize)) s.deviceSink = openal.OpenDevice("") s.contextSink = s.deviceSink.CreateContext() s.contextSink.Activate() s.buffer = make([]byte, gumble.AudioMaximumFrameSize) s.link = client.AttachAudio(s) return s, nil }
func New(client *gumble.Client) *State { l := lua.NewState() state := &State{ Client: client, LState: l, listeners: make(map[string][]lua.LValue), } t := l.NewTable() t.RawSetString("On", luar.New(l, state.apiOn)) t.RawSetString("Disconnect", luar.New(l, state.apiDisconnect)) state.table = t l.SetGlobal("piepan", t) { s := l.NewTable() s.RawSetString("New", luar.New(l, state.apiAudioNew)) s.RawSetString("IsPlaying", luar.New(l, state.apiAudioIsPlaying)) s.RawSetString("Current", luar.New(l, state.apiAudioCurrent)) s.RawSetString("NewTarget", luar.New(l, state.apiAudioNewTarget)) s.RawSetString("SetTarget", luar.New(l, state.apiAudioSetTarget)) s.RawSetString("Bitrate", luar.New(l, state.apiAudioBitrate)) s.RawSetString("SetBitrate", luar.New(l, state.apiAudioSetBitrate)) t.RawSetString("Audio", s) } { s := l.NewTable() s.RawSetString("New", luar.New(l, state.apiTimerNew)) t.RawSetString("Timer", s) } { s := l.NewTable() s.RawSetString("New", luar.New(l, state.apiProcessNew)) t.RawSetString("Process", s) } client.Attach(state) return state }