Skip to content
/ std Public

MTPROTO helper library and tools, tailored for bot & channel automation, groups or channel monitoring, managing sessions and scraping.

License

Notifications You must be signed in to change notification settings

prdsrm/std

Repository files navigation

std: simpler td

Nix Go Postgres

MTPROTO helper library and tools, tailored for bot & channel automation, groups or channel monitoring, managing sessions and scraping.

Features

Installation

Run the following in your Go project:

go get github.com/prdsrm/std

Usage

Scrape similar channels example, (here, we get the channels similar to Pavel Durov personal channel):

package main

import (
	"context"
	"fmt"
	"log"

	examples "github.com/gotd/td/examples"
	"github.com/gotd/td/telegram"
	"github.com/gotd/td/telegram/auth"
	"github.com/gotd/td/tg"

	"github.com/prdsrm/std/channels"
	"github.com/prdsrm/std/session"
)

func run(ctx context.Context, client *telegram.Client, dispatcher tg.UpdateDispatcher, options telegram.Options) error {
	channels, err := channels.GetSimilarChannels(ctx, client, "durov")
	if err != nil {
		return err
	}
	for _, channel := range channels {
		fmt.Println("Channel: ", channel.ID, channel.Username)
	}
	return nil
}

func main() {
	authOpt := auth.SendCodeOptions{}
	flow := auth.NewFlow(examples.Terminal{}, authOpt)
	err := session.Connect(run, session.Windows(), 2040, "b18441a1ff607e10a989891a5462e627", "", "", flow)
	if err != nil {
		log.Fatalln("can't connect: ", err)
	}
}

You can run this example, just create a main.go file, and install the library with go get, then run go run.

Bot automation example, extracting KOLs data from https://t.me/spydefi_bot:

package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"regexp"
	"strconv"

	"github.com/gotd/td/telegram"
	"github.com/gotd/td/tg"

	"github.com/prdsrm/std/bot"
	"github.com/prdsrm/std/messages"
	"github.com/prdsrm/std/session"
	"github.com/prdsrm/std/utils"
)

var expr = `(?m)Statsfor\@([a-zA-Z0-9_]{4,32}):Consistency:([0-9.]{1,3})%NumberofAlphaCalls:([0-9]+)BestCall:([a-zA-Z0-9.]+)(\(x[0-9.]+\))LastCall:([a-zA-Z0-9]+)(\(x[0-9.]+\))AverageCallMarketcap:\$([0-9.]+)(K|M|B)AverageXPerCall:x([0-9.]+)TotalCallsTracked:(\d+)NumberofAchievementCalls:calls:(\d+)calls:(\d+)TotalAchievements:(\d+)AchievementCallsrefertocallsthathavegonex2\+asperourparameters`
var re = regexp.MustCompile(expr)

func saveSpydefiChannelData(ctx messages.MonitoringContext) error {
	cleanedMessage := utils.RemoveSpacesAndNewlines(ctx.GetMessage().Message)
	for _, match := range re.FindAllStringSubmatch(cleanedMessage, -1) {
		username := match[1]
		averageCallMC := match[8]
		numberMC, err := strconv.ParseFloat(averageCallMC, 2)
		if err != nil {
			return err
		}
		mc := int(numberMC)
		averageCallMCUnit := match[9]
		var numberAverageCallMC int
		if averageCallMCUnit == "M" {
			numberAverageCallMC = mc * 1_000_000
		}
		if averageCallMCUnit == "K" {
			numberAverageCallMC = mc * 1_000
		} else {
			numberAverageCallMC = mc * 1_000_000_000
		}
		averageCallX := match[10]
		numberAverageCallX, _ := strconv.ParseFloat(averageCallX, 2)

		// NOTE: starting from here, you could start saving the result in a database or something similar.
		fmt.Println("Data: ", username, numberAverageCallMC, numberAverageCallX)
		return messages.EndConversation
	}
	if cleanedMessage == "ThisKOLChannelwasnotfoundinournetworkMakesureyouhaveenteredtheusernamecorrectly!Youcanalsousethe/trackme<@username>featuretosubmitanychannelstobetracked." {
		fmt.Println("This channel does not exist, in the spydefi database.")
		return messages.EndConversation
	}
	return nil
}

func listen(ctx context.Context, client *telegram.Client, dispatcher tg.UpdateDispatcher, options telegram.Options) error {
	fmt.Println("Successfully connected to the bot")
	automation, err := bot.NewAutomation(ctx, client, dispatcher, "spydefi_bot", true)
	if err != nil {
		return err
	}
	fmt.Println("Sending start message with params")
	// NOTE: channel is completely random.
	err = automation.SendStartMessageWithParams("tggemarcheologisttelegram-1001942713434")
	if err != nil {
		return err
	}
	automation.Handle(re, saveSpydefiChannelData)
	err = automation.Listen()
	if err != nil {
		return err
	}
	return nil
}

func main() {
	phone := os.Getenv("PHONE_NUMBER")
	password := os.Getenv("PASSWORD")
	sessionString := os.Getenv("SESSION_STRING")
	flow := session.GetNewDefaultAuthConversator(phone, password)
	err := session.Connect(listen, session.Windows(), 2040, "b18441a1ff607e10a989891a5462e627", sessionString, "", flow)
	if err != nil {
		log.Fatalln("can't connect: ", err)
	}
}

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

BSD-3-Clause license, because FreeBSD is great