This document will guide you on, How to add a module in the GIGA userbot. GIGA is a Go-based telegram userbot and Go is a compiled language, so it is unlikely that we add a module to GIGA during runtime. Instead, we can add up the {module_name}.go
file to the source code and build it again.
Please scroll down to know more about the modules of GIGA.
In order to make sure the automatic behaviour of loading modules, we use reflect
package from the go standard packages to fetch all the methods of a struct named module
located in the the modules directed inside modules.go
file.
A new module can be loaded to GIGA by defining a new method to module
struct corresponding to the module being loaded.
Let "Foo" be the name of the module, we want to import in the userbot. Hence, we will create a file named foo.go
in the modules directory and define a method named LoadFoo(dispatcher *dispatcher.CustomDispatcher)
All the handlers will be allocated to the main dispatcher stream through this LoadFoo
method.
package modules
import (
"github.com/celestix/gotgproto/dispatcher"
)
func (*module) LoadFoo(dp *dispatcher.CustomDispatcher) {
// Handlers will be allocated to dispatcher through this function.
}
The module
struct contains the basic needs of a module like dispatcher
, logger
, etc.
Here is the representation of module
struct as Go code:
type module struct {
Logger *logger.Logger
}
Dispatcher is not included in the fields because it is passed through the method calls as we have seen above in the code snippet of loading a module.
You can create logger for a module using the Logger
field of module
struct.
var log = m.Logger.Create("FOO")
Handlers are mapped functions which are called when a new telegram update is processed. Though we may not need to call all of them on every update so there exist some precoditional ones and filters for the purpose.
For example, to create a handler for handling a command named "foo", having usage like .foo
, we will use command handler as follows:
dp.AddHandler(handlers.NewCommand("foo", responseFunction))
where responseFunction is function which would look like:
func responseFcuntion(ctx *ext.Context, u *ext.Update) error {
return nil
}
There are many such conditional handlers provided by the GoTGProto package.
In order to add help section for your module, you have to call SetModuleHelp
function of helpmaker
package in the main module loading function.
package modules
import (
"github.com/celestix/gotgproto/dispatcher"
)
func (*module) LoadFoo(dp *dispatcher.CustomDispatcher) {
var l = m.Logger.Create("FOO")
defer l.ChangeLevel(logger.LevelInfo).Println("LOADED")
// foo is the module name and second argument is the help string corresponding to it.
helpmaker.SetModuleHelp("foo", "help here")
}
- ALWAYS CREATE a logger and "LOADED" print line statement everytime you create a new module.
- ALWAYS ADD message handlers to unique handler groups.
- NEVER USE
dispatcher.EndGroups
in return statement of message handlers. - NEVER ADD any other argument to Load method of the module than the
*dispatcher.CustomDispatcher
Here is an example module to understand the concept better, named as "Foo":
package modules
import (
"fmt"
"github.com/celestix/gotgproto/dispatcher"
"github.com/celestix/gotgproto/dispatcher/handlers"
"github.com/celestix/gotgproto/dispatcher/handlers/filters"
"github.com/celestix/gotgproto/ext"
"github.com/anonyindian/logger"
"github.com/gigauserbot/giga/bot/helpmaker"
)
func (m *module) LoadFoo(dispatcher *dispatcher.CustomDispatcher) {
var l = m.Logger.Create("FOO")
defer l.ChangeLevel(logger.LevelInfo).Println("LOADED")
helpmaker.SetModuleHelp("foo", `
Foo is an example module.
<b>Commands</b>:
• <code>.foo</code>: Example command for foo module
`)
// authorised() decorator ensures that the command is not usabe by anyone
// other than the authorised users i.e. you and sudos.
dispatcher.AddHandler(handlers.NewCommand("foo", authorised(foo)))
dispatcher.AddHandlerToGroup(handlers.NewMessage(filters.Message.All, fooMessage), 12)
}
func foo(ctx *ext.Context, u *ext.Update) error {
fmt.Println("You used .foo command")
return dispatcher.EndGroups
}
func fooMessage(ctx *ext.Context, u *ext.Update) error {
fmt.Println("You got a new message update")
// NEVER use EndGroups in a message handler response,
// use nil or ContinueGroups instead.
return nil
}