Collection of Technical Interview Questions solved with Go
Slack Bot Framework
shomali11/util 179
A collection of useful utility functions
Simplifies the parallelization of function calls.
SQL Query Results Pretty Printing
A Grid based 2D Graphics library
A cache that resembles storing, restocking and retrieving items from a fridge
Command evaluator and parser
Go Redis Client
Eventbus
pull request commentshomali11/slacker
Allow event handler to be configured
@smoya @mmcdole You are right.
I have another idea. How about we extract this switch block into its own method that returns bool and err to indicate whether a message was handled (by the internal logic), if so, no need to pass the event to the fallback handler, otherwise we do.
For example:
func (s *Slacker) isEventHandled(msg slack.RTMEvent) (bool, error) {
switch event := msg.Data.(type) {
case *slack.ConnectedEvent:
if s.initHandler == nil {
continue
}
go s.initHandler()
return true, nil
case *slack.MessageEvent:
if s.isFromBot(event) {
return false, nil
}
if !s.isBotMentioned(event) && !s.isDirectMessage(event) {
return false, nil
}
go s.handleMessage(ctx, event)
return true, nil
case *slack.RTMError:
if s.errorHandler == nil {
continue
}
go s.errorHandler(event.Error())
return true, nil
case *slack.InvalidAuthEvent:
return true, errors.New(invalidToken)
default:
return false, nil
}
}
This way, the Listen method would look like this:
// Listen receives events from Slack and each is handled as needed
func (s *Slacker) Listen(ctx context.Context) error {
s.prependHelpHandle()
go s.rtm.ManageConnection()
for {
select {
case <-ctx.Done():
s.rtm.Disconnect()
return ctx.Err()
case msg, ok := <-s.rtm.IncomingEvents:
if !ok {
return nil
}
handled, err := s.isEventHandled(msg)
if err != nil {
return err
}
if handled {
continue
}
if s.fallbackEventHandler == nil {
continue
}
go s.fallbackEventHandler(event)
}
}
I think this might work for everyone? What do you guys think?
comment created time in 7 days
pull request commentshomali11/slacker
Allow event handler to be configured
I would like to hear both of your opinions on this @smoya and @mmcdole
The main issue I see is that if someone overrides the Event Handler, then the following methods are irrelevant https://github.com/shomali11/slacker/blob/master/examples/14/example14.go#L15-L29
Especially that overriding the event handler, would make those methods unusable as they are not being called internally. Moreover, the user will have to reimplement the message handling from scratch and rewriting a ton of the code to wire everything together.
It feels that this is not the right approach. So I went back and read your earlier messages about wanting to access the raw message.
What if we inserted a tracker here ... https://github.com/shomali11/slacker/blob/master/slacker.go#L143
So that things look like:
go s.rawEventHandler(msg.Data)
switch event := msg.Data.(type) {
case *slack.ConnectedEvent:
if s.initHandler == nil {
continue
}
go s.initHandler()
case *slack.MessageEvent:
if s.isFromBot(event) {
continue
}
if !s.isBotMentioned(event) && !s.isDirectMessage(event) {
continue
}
go s.handleMessage(ctx, event)
case *slack.RTMError:
if s.errorHandler == nil {
continue
}
go s.errorHandler(event.Error())
case *slack.InvalidAuthEvent:
return errors.New(invalidToken)
default:
if s.fallbackEventHandler == nil {
continue
}
go s.fallbackEventHandler(event)
}
This way you can have access to the raw event and have the ability to act upon it without having to reimplement everything else. Would this work for both of your cases?
comment created time in 9 days
issue commentshomali11/slacker
I believe you will need to use the underlying slack-go library to get the "display name"
Example 7 shows you how to access the library https://github.com/shomali11/slacker/blob/master/examples/7/example7.go
This is the users file https://github.com/slack-go/slack/blob/master/users.go
comment created time in 10 days
pull request commentshomali11/slacker
Allow event handler to be configured
@mmcdole If that is the desired behavior, I guess I am fine with @smoya's solution. Let's hope he resolves the conflicting files and we can merge it.
comment created time in 11 days
push eventshomali11/go-interview
commit sha 434db55b01dd64b99f54b5fc3efa6f7a26de3499
Print Trees in Zig Zag
push time in 12 days
issue commentshomali11/slacker
This only works with "classic" slack apps
Absolutely! Some of the features here we suggested and/or created by awesome contributors!
I definitely think we need to support both APIs just in case somehow. The question is how to make it as easy and intuitive to the user of slacker
I did some research. At the time when nlopes started the go-slack project, there was only support for RTM and slacker was built on top of that (https://github.com/slack-go/slack/blob/master/examples/websocket/websocket.go)
It seems that go-slack now supports an Events API as seen here (https://github.com/slack-go/slack/blob/master/examples/eventsapi/events.go). I wonder if we can leverage this somehow.
comment created time in 17 days
issue commentshomali11/slacker
This only works with "classic" slack apps
Interesting. We will have to look into this further and see how it affects slacker and what we need to do to support both cases.
comment created time in 17 days
issue closedshomali11/go-interview
clean implementation of prime numbers, however, 2 is a prime number :) https://github.com/shomali11/go-interview/blob/master/numbers/primes/primes.go
closed time in a month
golarkissue commentshomali11/go-interview
LOL! I am so embarrassed. Great catch!
comment created time in a month
push eventshomali11/go-interview
commit sha 115de3e6efe3b18e5bca8d63b4fda1430f3100c6
Improve Prime test
push time in a month
issue closedshomali11/slacker
What is required on the slack app setup side for the example 1 for the simple bot.Listen() to work for ping?
closed time in a month
alexcurtinissue closedshomali11/go-interview
Why we should set structure variable to nil after use?
Firstly, really appreciate your sharing the collection of Golang technical interview questions, which really help me to learn Golang as a beginner.
I have a question when I read your doubly lined list Implement. I found you will set the structure variable to nil after using it.
For example, in the following function: https://github.com/shomali11/go-interview/blob/master/datastructures/linkedlists/doublylinkedlists/doubly_linked_lists.go#L94
// GetIndexOf returns the index of the first occurence
func (s *DoublyLinkedList) GetIndexOf(value interface{}) int {
index := 0
current := s.head
for current != nil {
if value == current.Value {
return index
}
current = current.Next
index++
}
current = nil <-- This line
return -1
}
Will the function cause a leak if it isn't set to nil?
It is probably a dumb question. Could you shed some light?
Thanks in advance!
closed time in a month
horis233issue commentshomali11/go-interview
Why we should set structure variable to nil after use?
That is probably unnecessary since the for loop will exist when the current is nil.
Good catch!
comment created time in a month
issue commentshomali11/commander
Parsing of text with non-breaking space has incorrect results.
Good question. I think that this is something that slacker should be handling but I am open to learning your thoughts.
My only concern would be when does UTF-8 characters need to be handled and when should they not be. For example, when the user enters a UTF-8 character in the message.
comment created time in 2 months
issue commentshomali11/slacker
Expose the slack client in AuthorizedFunc
You are most welcome! Thank you for inspiring this new change.
Hopefully this makes everything more intuitive and easier to work with
comment created time in 2 months
issue commentshomali11/slacker
Expose the slack client in AuthorizedFunc
Ok. I pushed the changes. Check out the new examples and README.
Let me know if this is a better experience now.
comment created time in 2 months
push eventshomali11/slacker
commit sha 3156f073f291e5d57a20ce5ae792bdf038516e60
Add BotContext to clean up Handler Signatures
push time in 2 months
issue commentshomali11/slacker
Expose the slack client in AuthorizedFunc
I see what you mean.
I guess one way to clean things up for you and everyone else would be to remove the Client and RTM from the Response object and instead expand the AuthorizationFunc and Handler function to include some custom context object as a parameter which will include the Client and possibly any other future necessary stuff.
comment created time in 2 months
issue commentshomali11/slacker
Expose the slack client in AuthorizedFunc
I am confused. Why would you need to create a new bot object?
Here is an example of what I mean:
package main
import (
"context"
"github.com/shomali11/slacker"
"log"
)
func main() {
bot := slacker.NewClient("<YOUR SLACK BOT TOKEN>")
authorizedUsers := []string{"<USER ID>"}
authorizedDefinition := &slacker.CommandDefinition{
Description: "Very secret stuff",
AuthorizationFunc: func(request slacker.Request) bool {
...
client := bot.Client()
userInfo, _ := client.GetUserInfo(request.Event().User)
return AuthorizeFromDatabase("some-command", user.Profile.Email)
},
Handler: func(request slacker.Request, response slacker.ResponseWriter) {
response.Reply("You are authorized!")
},
}
bot.Command("secret", authorizedDefinition)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
err := bot.Listen(ctx)
if err != nil {
log.Fatal(err)
}
}
comment created time in 2 months
issue commentshomali11/slacker
Expose the slack client in AuthorizedFunc
Come to think about it, we should probably remove access to the RTM and Client from the Response object since both are accessible from the Slacker object
comment created time in 2 months
issue commentshomali11/slacker
Expose the slack client in AuthorizedFunc
You do not need the response object to access the Client.
You can access it from the Slacker object too
https://github.com/shomali11/slacker/blob/master/slacker.go#L71
So when you do something like
bot := slacker.NewClient("<YOUR SLACK BOT TOKEN>")
You can get the client from bot.Client()
comment created time in 2 months
issue closedshomali11/slacker
Expose the slack client in AuthorizedFunc
We'd like to be able to authenticate a Slack user with a backend database that has no concept of Slack User IDs, but to get the requesting users profile details we need access to the Slack client. Simple example:
var myCommand = &slacker.CommandDefinition {
...
AuthorizationFunc: func(request slacker.Request, client slack.Client) bool {
...
userInfo, _ := client.GetUserInfo(request.Event().User)
return AuthorizeFromDatabase("some-command", user.Profile.Email)
},
...
}
closed time in 2 months
arussoissue commentshomali11/slacker
Expose the slack client in AuthorizedFunc
You should be able to do that following Example 7
https://github.com/shomali11/slacker/blob/master/examples/7/example7.go
comment created time in 2 months
push eventshomali11/go-interview
commit sha 8cd7ee6c3ab2d9ea9144724467304a10cee11784
Primes
push time in 2 months
push eventshomali11/gridder
commit sha cff664637ded33e0c98405d96052e3a77f3ed5c9
Improve README
push time in 3 months
push eventshomali11/gridder
commit sha dfad6389320ae4d0918f1d52caf0af31dca54431
Add Dashes styles
push time in 3 months
pull request commentavelino/awesome-go
@panjf2000 Done. Improved it to be over 90%
comment created time in 3 months
push eventshomali11/gridder
commit sha 1504bcaa1a5a1267ae38856a22e45e6706218d78
Add tests
push time in 3 months
pull request commentavelino/awesome-go
@panjf2000 Added gocover link
comment created time in 3 months
push eventshomali11/gridder
commit sha d850b5eacca7a04f979a8bc2624115a8fadbaef2
Add tests
push time in 3 months