summary refs log tree commit diff
path: root/commands.py
blob: 0740916b13ca97f5cb92011448890d62fab7309e (plain)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
from functools import wraps
from irctokens import build

import importlib
import sys
import random


class Command:
    def __init__(self, config):
        self.config = config
        self.commands = []

    def mesg(self, msg, t=None):
        self.util.mesg(msg, t)

    def notice(self, msg):
        self.util.notice(msg)

    def action(self, msg):
        self.util.action(msg)

    def send(self, msg):
        self.util.send(msg)

    def err_perm(self, level="admin"):
        self.mesg(f"Error: insufficient privileges, you lack {level} access")

    def adm(func, *args, **kwargs):
        """decorator for admin commands"""
        global adm_cmds
        try:
            if func.__name__ not in adm_cmds and func.__name__ != "_":
                adm_cmds.append(func.__name__)
        except NameError:
            adm_cmds = []
            if func.__name__ not in adm_cmds and func.__name__ != "_":
                adm_cmds.append(func.__name__)

        @wraps(func)
        def _(self, *args, **kwargs):
            if func.__name__ == "help":
                self.admin_commands = adm_cmds
            if not self.admin:
                self.err_perm()
            else:
                return func(
                    self,
                    self.prefix,
                    self.line,
                    self.pm,
                    self._line,
                    self.admin,
                    self.mesg,
                )

        return _

    def cmd(func, *args, **kwargs):
        """decorator for user commands"""
        global cmds
        try:
            if func.__name__ not in cmds and func.__name__ != "_":
                cmds.append(func.__name__)
        except NameError:
            cmds = []
            if func.__name__ not in cmds and func.__name__ != "_":
                cmds.append(func.__name__)

        @wraps(func)
        def _(self, *args, **kwargs):
            if func.__name__ == "help":
                self.commands = cmds
            if func.__name__ not in self.config.cmd.disabled:
                return func(
                    self,
                    self.prefix,
                    self.line,
                    self.pm,
                    self._line,
                    self.admin,
                    self.mesg,
                )

        return _

    def internal(func, *args, **kwargs):
        """decorator for commands like ctcp which are for internal use, but use normal args template"""
        global cmds
        if func.__name__ in cmds:
            cmds.remove(func.__name__)
        return func

    def preq_cmd(self):  # command prequisites / triggers
        cmd = self.line
        needs_prefix = True
        # self.mesg(f"attempting command: {cmd}")
        if cmd == "help" or cmd.startswith("help "):
            command = "help"
        elif cmd.startswith("quit"):
            command = "quit"
        elif cmd.startswith("echo "):
            command = "echo"
        elif cmd.startswith("roll ") or cmd == "roll":
            command = "dice"
        elif cmd.startswith("pick ") or cmd.startswith("choose "):
            command = "choose"
        elif cmd.startswith("yt ") or self.YouTube.match_urls(self.YouTube, cmd) != []:
            command = "yt"
            needs_prefix = False
        elif cmd.startswith("w ") or cmd.startswith("weather "):
            command = "weather"
        elif cmd.startswith("me "):
            command = "me"
        elif cmd == "crapdate" or cmd.startswith("crapdate "):
            command = "crapdate"
        elif cmd == "dbg" or cmd.startswith("dbg "):
            command = "dbg"
        elif cmd == "dbg2" or cmd.startswith("dbg2 "):
            command = "dbg2"
        elif cmd == "version" or cmd == "ver":
            command = "version"
        elif cmd.startswith("\x01") or self.is_ctcp:
            command = "ctcp"
        else:
            # self.mesg(cmd)
            return
        if command not in self.config.cmd.disabled:
            if needs_prefix == False:
                eval(f"self.{command}()")
            elif not (self.prefix == None and self.pm == False):
                eval(f"self.{command}()")

    #       else:
    #           self.mesg("this ain't a valid commanderoonie, you twat")

    def getversion(self):
        with open(self.config.self.gitdir + ".git/logs/HEAD") as f:
            for l in f:
                pass
        return l.split()[1]

    @internal
    @cmd
    def ctcp(self, prefix, cmd, pm, line, admin, mesg):
        """CTCP responses"""
        notice = self.notice
        ctcp = cmd[1:]
        ctcp_upper = ctcp.upper()
        if not ctcp.endswith("\x01"):
            ctcp = ctcp + "\x01"
        if ctcp_upper.startswith("PING"):
            ctcp = (
                "\x01PING"
                + ("" if 1 == len(ctcp.split(" ")) else " ")
                + " ".join(ctcp.split(" ")[1:])
            )
            print(ctcp)
            self.notice(ctcp)
        if ctcp_upper.startswith("SOURCE"):
            self.notice("\x01SOURCE " + self.config.self.source + "\x01")
        elif ctcp_upper.startswith("VERSION"):
            self.notice(f"\x01VERSION {self.getversion()}\x01")
        elif ctcp_upper.startswith("FINGER"):
            self.notice(
                f"\x01FINGER {self.config.self.nick} version {self.getversion()} ({self.config.self.source})\x01"
            )
        elif ctcp_upper.startswith("USERINFO"):
            self.notice("\x01USERINFO pawky's crude IRC bot\x01")
        elif ctcp_upper.startswith("CLIENTINFO"):
            self.notice("\x01CLIENTINFO USERINFO PING SOURCE FINGER VERSION\x01")

    @adm
    def quit(self, prefix, cmd, pm, line, admin, mesg):
        if admin and (cmd == "q" or cmd == "quit"):
            self.util.quit()
        elif admin and (cmd.startswith("q ") or cmd.startswith("quit ")):
            self.util.quit(cmd.split(" ", 1)[1])

    @adm
    def crapdate(self, prefix, cmd, pm, line, admin, mesg):
        """hacky and crappy update command, don't use it, lol"""
        args = cmd.split()[1:]
        if not args:
            args = [""]
        popen = __import__("os").popen
        # mesg(args)
        if args[0] in ["log", "list"]:
            if len(args) == 1:
                args = args + ["", 3]
            elif len(args) < 3:
                args = args + ["3"]
            for i in (
                popen(f"git log --pretty=oneline --abbrev-commit {args[1]}")
                .read()
                .split("\n", int(args[2]))
            ):
                mesg(i)
        else:
            mesg(popen("git pull").read())
            mesg(popen("git status|tr '\\n' ' '").read())

    @adm
    def dbg(self, prefix, cmd, pm, line, admin, mesg):
        """temporary debug command, subject to change A LOT"""
        mesg(dir())

    @cmd
    def yt(self, prefix, cmd, pm, line, admin, mesg):
        """youtube"""
        YouTube = self.YouTube
        if cmd.startswith("yt "):
            cmd = cmd[3:]
        try:
            YouTube.premature_optimization = self.config.cmd.yt_premature_opt
        except AttributeError:
            pass
        print(f"  YT premature_optimization={YouTube.premature_optimization}")
        urls = YouTube.match_urls(YouTube, cmd)
        yt_failed = False
        for video in urls:
            if yt_failed == True:
                yt_failed = False
                break
            try:
                a, yt_failed = YouTube.yt(YouTube, video)
            except Exception as e:
                a = e
                yt_failed = True
            mesg(a)

    @cmd
    def echo(self, prefix, cmd, pm, line, admin, mesg):
        """simple echo command | "echo ABC..." """
        mesg("\x7f" + cmd.split(" ", 1)[1])

    @cmd
    def choose(self, prefix, cmd, pm, line, admin, mesg):
        """simple random choice command | "choose A B C..." """
        mesg("I choose: " + str(random.choice(cmd.split(" ", 1)[1].split(" "))))

    @cmd
    def dice(self, prefix, cmd, pm, line, admin, mesg):
        """simple dice command | "roll [N[d[M]]]" where N is number of dice, and M is number of faces"""
        cmd = cmd.split(" ", 1)[1]
        amount, faces = 1, 6
        try:
            amount = 0 + int(cmd.split("d", 1)[0])
            faces = 0 + int(cmd.split("d", 1)[1])
        except:
            pass
        if not str(amount).isnumeric() or amount > 100:
            amount = 1
        if not str(faces).isnumeric() or faces > 100:
            faces = 6
        mesg(
            f"rolling {amount}d{faces}: "
            + str([random.choice([i for i in range(faces)]) for n in range(amount)])
        )

    @cmd
    def version(self, prefix, cmd, pm, line, admin, mesg):
        """version"""
        mesg(
            f"{self.config.self.nick} version {self.getversion()} ({self.config.self.source})"
        )

    @adm
    def dbg2(self, prefix, cmd, pm, line, admin, mesg):
        """version"""
        with open(self.config.self.gitdir + ".git/logs/HEAD") as f:
            for l in f:
                pass
        mesg("version " + l.split()[1])

    @cmd
    def me(self, prefix, cmd, pm, line, admin, mesg):
        """simple /me command"""
        self.action(cmd.split(" ", 1)[1])

    @cmd
    def help(self, prefix, cmd, pm, line, admin, mesg):
        global adm_cmds
        global cmds
        disabled_commands = self.config.cmd.disabled
        admin_commands, commands = [], []
        for i in ["exec", "eval", "reload"]:
            if i not in adm_cmds:
                adm_cmds.append(i)
        for i in adm_cmds:
            if i not in disabled_commands:
                admin_commands.append(i)
        for i in cmds:
            if i not in admin_commands and i not in disabled_commands:
                commands.append(i)
        prefixes = '"' + '", "'.join(self.config.cmd.prefixes) + '"'
        admin_commands = ", ".join(admin_commands)
        try:
            topic = cmd.split(" ", 1)[1]
        except IndexError:
            topic = None
        try:
            self_nick = self.self_nick
        except IndexError:
            self_nick = None

        abs_topics = {"prefixes": f'available prefixes are {prefixes} or "{self_nick}"'}
        if topic == None:
            mesg(f"available topics: " + ", ".join(list(abs_topics.keys())))
            mesg(f"available commands: " + ", ".join(commands))
            if admin:
                mesg(f"admin commands: {admin_commands}")
        else:
            try:
                mesg(f"{topic}: " + eval(f"self.{topic}.__doc__"))
            except (TypeError, AttributeError) as e:
                #                mesg(str( e.__class__.__name__ ))
                if topic in abs_topics:
                    mesg(f"{topic}: " + abs_topics[topic])
                else:
                    mesg(f'no help available for "{topic}"...')
            except Exception as e:
                mesg(str(e.__class__) + " " + str(e))