-
Notifications
You must be signed in to change notification settings - Fork 0
/
chat.go
136 lines (111 loc) · 4.39 KB
/
chat.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package cmd
import (
"fmt"
"math"
"strings"
"github.com/spf13/cobra"
"github.com/iyear/tdl/app/chat"
"github.com/iyear/tdl/pkg/logger"
)
func NewChat() *cobra.Command {
cmd := &cobra.Command{
Use: "chat",
Short: "A set of chat tools",
}
cmd.AddCommand(NewChatList(), NewChatExport(), NewChatUsers())
return cmd
}
func NewChatList() *cobra.Command {
var opts chat.ListOptions
cmd := &cobra.Command{
Use: "ls",
Short: "List your chats",
RunE: func(cmd *cobra.Command, args []string) error {
return chat.List(logger.Named(cmd.Context(), "ls"), opts)
},
}
cmd.Flags().VarP(&opts.Output, "output", "o", fmt.Sprintf("output format: [%s]", strings.Join(chat.OutputNames(), ", ")))
cmd.Flags().StringVarP(&opts.Filter, "filter", "f", "true", "filter chats by expression")
return cmd
}
func NewChatExport() *cobra.Command {
var opts chat.ExportOptions
cmd := &cobra.Command{
Use: "export",
Short: "export messages from (protected) chat for download",
RunE: func(cmd *cobra.Command, args []string) error {
switch opts.Type {
case chat.ExportTypeTime, chat.ExportTypeId:
// set default value
switch len(opts.Input) {
case 0:
opts.Input = []int{0, math.MaxInt}
case 1:
opts.Input = append(opts.Input, math.MaxInt)
}
if len(opts.Input) != 2 {
return fmt.Errorf("input data should be 2 integers when export type is %s", opts.Type)
}
// sort helper
if opts.Input[0] > opts.Input[1] {
opts.Input[0], opts.Input[1] = opts.Input[1], opts.Input[0]
}
case chat.ExportTypeLast:
if len(opts.Input) != 1 {
return fmt.Errorf("input data should be 1 integer when export type is %s", opts.Type)
}
default:
return fmt.Errorf("unknown export type: %s", opts.Type)
}
return chat.Export(logger.Named(cmd.Context(), "export"), &opts)
},
}
const (
_type = "type"
_chat = "chat"
input = "input"
)
cmd.Flags().VarP(&opts.Type, _type, "T", fmt.Sprintf("export type: [%s]", strings.Join(chat.ExportTypeNames(), ", ")))
cmd.Flags().StringVarP(&opts.Chat, _chat, "c", "", "chat id or domain. If not specified, 'Saved Messages' will be used")
// topic id and message id is the same field in tg.MessagesGetRepliesRequest
cmd.Flags().IntVar(&opts.Thread, "topic", 0, "specify topic id")
cmd.Flags().IntVar(&opts.Thread, "reply", 0, "specify channel post id")
cmd.Flags().IntSliceVarP(&opts.Input, input, "i", []int{}, "input data, depends on export type")
cmd.Flags().StringVarP(&opts.Filter, "filter", "f", "true", "filter messages by expression, defaults to match all messages. Specify '-' to see available fields")
cmd.Flags().StringVarP(&opts.Output, "output", "o", "tdl-export.json", "output JSON file path")
cmd.Flags().BoolVar(&opts.WithContent, "with-content", false, "export with message content")
cmd.Flags().BoolVar(&opts.Raw, "raw", false, "export raw message struct of Telegram MTProto API, useful for debugging")
cmd.Flags().BoolVar(&opts.All, "all", false, "export all messages including non-media messages, but still affected by filter and type flag")
// completion and validation
_ = cmd.RegisterFlagCompletionFunc(input, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// if user has already input something, don't do anything
if toComplete != "" {
return []string{}, cobra.ShellCompDirectiveNoFileComp
}
switch cmd.Flags().Lookup(_type).Value.String() {
case chat.ExportTypeTime.String():
return []string{"0,9999999"}, cobra.ShellCompDirectiveNoFileComp
case chat.ExportTypeId.String():
return []string{"0,9999999"}, cobra.ShellCompDirectiveNoFileComp
case chat.ExportTypeLast.String():
return []string{"100"}, cobra.ShellCompDirectiveNoFileComp
default:
return []string{}, cobra.ShellCompDirectiveNoFileComp
}
})
return cmd
}
func NewChatUsers() *cobra.Command {
var opts chat.UsersOptions
cmd := &cobra.Command{
Use: "users",
Short: "export users from (protected) channels",
RunE: func(cmd *cobra.Command, args []string) error {
return chat.Users(logger.Named(cmd.Context(), "users"), opts)
},
}
cmd.Flags().StringVarP(&opts.Output, "output", "o", "tdl-users.json", "output JSON file path")
cmd.Flags().StringVarP(&opts.Chat, "chat", "c", "", "domain id (channels, supergroups, etc.)")
cmd.Flags().BoolVar(&opts.Raw, "raw", false, "export raw message struct of Telegram MTProto API, useful for debugging")
return cmd
}