diff --git a/.apt/usr/bin/config/config.conf b/.apt/usr/bin/config/config.conf
deleted file mode 100644
index 82ceef724..000000000
--- a/.apt/usr/bin/config/config.conf
+++ /dev/null
@@ -1,771 +0,0 @@
-# Neofetch config file
-# https://github.com/dylanaraps/neofetch
-
-
-# See this wiki page for more info:
-# https://github.com/dylanaraps/neofetch/wiki/Customizing-Info
-print_info() {
- info title
- info underline
-
- info "OS" distro
- info "Host" model
- info "Kernel" kernel
- info "Uptime" uptime
- info "Packages" packages
- info "Shell" shell
- info "Resolution" resolution
- info "DE" de
- info "WM" wm
- info "WM Theme" wm_theme
- info "Theme" theme
- info "Icons" icons
- info "Terminal" term
- info "Terminal Font" term_font
- info "CPU" cpu
- info "GPU" gpu
- info "Memory" memory
-
- # info "GPU Driver" gpu_driver # Linux/macOS only
- # info "CPU Usage" cpu_usage
- # info "Disk" disk
- # info "Battery" battery
- # info "Font" font
- # info "Song" song
- # info "Local IP" local_ip
- # info "Public IP" public_ip
- # info "Users" users
- # info "Install Date" install_date
- # info "Locale" locale # This only works on glibc systems.
-
- info line_break
- info cols
- info line_break
-}
-
-
-# Kernel
-
-
-# Shorten the output of the kernel function.
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --kernel_shorthand
-# Supports: Everything except *BSDs (except PacBSD and PC-BSD)
-#
-# Example:
-# on: '4.8.9-1-ARCH'
-# off: 'Linux 4.8.9-1-ARCH'
-kernel_shorthand="off"
-
-
-# Distro
-
-
-# Shorten the output of the distro function
-#
-# Default: 'off'
-# Values: 'on', 'off', 'tiny'
-# Flag: --distro_shorthand
-# Supports: Everything except Windows and Haiku
-distro_shorthand="off"
-
-# Show/Hide OS Architecture.
-# Show 'x86_64', 'x86' and etc in 'Distro:' output.
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --os_arch
-#
-# Example:
-# on: 'Arch Linux x86_64'
-# off: 'Arch Linux'
-os_arch="on"
-
-
-# Uptime
-
-
-# Shorten the output of the uptime function
-#
-# Default: 'on'
-# Values: 'on', 'off', 'tiny'
-# Flag: --uptime_shorthand
-#
-# Example:
-# on: '2 days, 10 hours, 3 mins'
-# off: '2 days, 10 hours, 3 minutes'
-# tiny: '2d 10h 3m'
-uptime_shorthand="tiny"
-
-
-# Shell
-
-
-# Show the path to $SHELL
-#
-# Default: 'off'
-# Values: 'on', 'off'
-# Flag: --shell_path
-#
-# Example:
-# on: '/bin/bash'
-# off: 'bash'
-shell_path="on"
-
-# Show $SHELL version
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --shell_version
-#
-# Example:
-# on: 'bash 4.4.5'
-# off: 'bash'
-shell_version="on"
-
-
-# CPU
-
-
-# CPU speed type
-#
-# Default: 'bios_limit'
-# Values: 'scaling_cur_freq', 'scaling_min_freq', 'scaling_max_freq', 'bios_limit'.
-# Flag: --speed_type
-# Supports: Linux with 'cpufreq'
-# NOTE: Any file in '/sys/devices/system/cpu/cpu0/cpufreq' can be used as a value.
-speed_type="bios_limit"
-
-# CPU speed shorthand
-#
-# Default: 'off'
-# Values: 'on', 'off'.
-# Flag: --speed_shorthand.
-# NOTE: This flag is not supported in systems with CPU speed less than 1 GHz
-#
-# Example:
-# on: 'i7-6500U (4) @ 3.1GHz'
-# off: 'i7-6500U (4) @ 3.100GHz'
-speed_shorthand="off"
-
-# Enable/Disable CPU brand in output.
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --cpu_brand
-#
-# Example:
-# on: 'Intel i7-6500U'
-# off: 'i7-6500U (4)'
-cpu_brand="off"
-
-# CPU Speed
-# Hide/Show CPU speed.
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --cpu_speed
-#
-# Example:
-# on: 'Intel i7-6500U (4) @ 3.1GHz'
-# off: 'Intel i7-6500U (4)'
-cpu_speed="off"
-
-# CPU Cores
-# Display CPU cores in output
-#
-# Default: 'logical'
-# Values: 'logical', 'physical', 'off'
-# Flag: --cpu_cores
-# Support: 'physical' doesn't work on BSD.
-#
-# Example:
-# logical: 'Intel i7-6500U (4) @ 3.1GHz' (All virtual cores)
-# physical: 'Intel i7-6500U (2) @ 3.1GHz' (All physical cores)
-# off: 'Intel i7-6500U @ 3.1GHz'
-cpu_cores="off"
-
-# CPU Temperature
-# Hide/Show CPU temperature.
-# Note the temperature is added to the regular CPU function.
-#
-# Default: 'off'
-# Values: 'C', 'F', 'off'
-# Flag: --cpu_temp
-# Supports: Linux, BSD
-# NOTE: For FreeBSD and NetBSD-based systems, you'll need to enable
-# coretemp kernel module. This only supports newer Intel processors.
-#
-# Example:
-# C: 'Intel i7-6500U (4) @ 3.1GHz [27.2°C]'
-# F: 'Intel i7-6500U (4) @ 3.1GHz [82.0°F]'
-# off: 'Intel i7-6500U (4) @ 3.1GHz'
-cpu_temp="off"
-
-
-# GPU
-
-
-# Enable/Disable GPU Brand
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --gpu_brand
-#
-# Example:
-# on: 'AMD HD 7950'
-# off: 'HD 7950'
-gpu_brand="off"
-
-# Which GPU to display
-#
-# Default: 'all'
-# Values: 'all', 'dedicated', 'integrated'
-# Flag: --gpu_type
-# Supports: Linux
-#
-# Example:
-# all:
-# GPU1: AMD HD 7950
-# GPU2: Intel Integrated Graphics
-#
-# dedicated:
-# GPU1: AMD HD 7950
-#
-# integrated:
-# GPU1: Intel Integrated Graphics
-gpu_type="dedicated"
-
-
-# Resolution
-
-
-# Display refresh rate next to each monitor
-# Default: 'off'
-# Values: 'on', 'off'
-# Flag: --refresh_rate
-# Supports: Doesn't work on Windows.
-#
-# Example:
-# on: '1920x1080 @ 60Hz'
-# off: '1920x1080'
-refresh_rate="on"
-
-
-# Gtk Theme / Icons / Font
-
-
-# Shorten output of GTK Theme / Icons / Font
-#
-# Default: 'off'
-# Values: 'on', 'off'
-# Flag: --gtk_shorthand
-#
-# Example:
-# on: 'Numix, Adwaita'
-# off: 'Numix [GTK2], Adwaita [GTK3]'
-gtk_shorthand="on"
-
-
-# Enable/Disable gtk2 Theme / Icons / Font
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --gtk2
-#
-# Example:
-# on: 'Numix [GTK2], Adwaita [GTK3]'
-# off: 'Adwaita [GTK3]'
-gtk2="off"
-
-# Enable/Disable gtk3 Theme / Icons / Font
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --gtk3
-#
-# Example:
-# on: 'Numix [GTK2], Adwaita [GTK3]'
-# off: 'Numix [GTK2]'
-gtk3="off"
-
-
-# IP Address
-
-
-# Website to ping for the public IP
-#
-# Default: 'http://ident.me'
-# Values: 'url'
-# Flag: --ip_host
-public_ip_host="http://ident.me"
-
-
-# Disk
-
-
-# Which disks to display.
-# The values can be any /dev/sdXX, mount point or directory.
-# NOTE: By default we only show the disk info for '/'.
-#
-# Default: '/'
-# Values: '/', '/dev/sdXX', '/path/to/drive'.
-# Flag: --disk_show
-#
-# Example:
-# disk_show=('/' '/dev/sdb1'):
-# 'Disk (/): 74G / 118G (66%)'
-# 'Disk (/mnt/Videos): 823G / 893G (93%)'
-#
-# disk_show=('/'):
-# 'Disk (/): 74G / 118G (66%)'
-#
-disk_show=('/')
-
-# Disk subtitle.
-# What to append to the Disk subtitle.
-#
-# Default: 'mount'
-# Values: 'mount', 'name', 'dir'
-# Flag: --disk_subtitle
-#
-# Example:
-# name: 'Disk (/dev/sda1): 74G / 118G (66%)'
-# 'Disk (/dev/sdb2): 74G / 118G (66%)'
-#
-# mount: 'Disk (/): 74G / 118G (66%)'
-# 'Disk (/mnt/Local Disk): 74G / 118G (66%)'
-# 'Disk (/mnt/Videos): 74G / 118G (66%)'
-#
-# dir: 'Disk (/): 74G / 118G (66%)'
-# 'Disk (Local Disk): 74G / 118G (66%)'
-# 'Disk (Videos): 74G / 118G (66%)'
-disk_subtitle="mount"
-
-
-# Song
-
-
-# Manually specify a music player.
-#
-# Default: 'auto'
-# Values: 'auto', 'player-name'
-# Flag: --music_player
-#
-# Available values for 'player-name':
-#
-# Google Play
-# Spotify
-# amarok
-# audacious
-# banshee
-# bluemindo
-# clementine
-# cmus
-# deadbeef
-# deepin-music
-# elisa
-# exaile
-# gnome-music
-# guayadeque
-# iTunes$
-# juk
-# lollypop
-# mocp
-# mopidy
-# mpd
-# pogo
-# pragha
-# qmmp
-# quodlibet
-# rhythmbox
-# spotify
-# tomahawk
-# xmms2d
-# yarock
-music_player="auto"
-
-# Print the Artist and Title on separate lines
-#
-# Default: 'off'
-# Values: 'on', 'off'
-# Flag: --song_shorthand
-#
-# Example:
-# on: 'Artist: The Fratellis'
-# 'Song: Chelsea Dagger'
-#
-# off: 'Song: The Fratellis - Chelsea Dagger'
-song_shorthand="off"
-
-
-# Install Date
-
-
-# Whether to show the time in the output
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --install_time
-#
-# Example:
-# on: 'Thu 14 Apr 2016 11:50 PM'
-# off: 'Thu 14 Apr 2016'
-install_time="on"
-
-# Set time format in the output
-#
-# Default: '24h'
-# Values: '12h', '24h'
-# Flag: --install_time_format
-#
-# Example:
-# 12h: 'Thu 14 Apr 2016 11:50 PM'
-# 24h: 'Thu 14 Apr 2016 23:50'
-install_time_format="12h"
-
-
-# Text Colors
-
-
-# Text Colors
-#
-# Default: 'distro'
-# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num'
-# Flag: --colors
-#
-# Each number represents a different part of the text in
-# this order: 'title', '@', 'underline', 'subtitle', 'colon', 'info'
-#
-# Example:
-# colors=(distro) - Text is colored based on Distro colors.
-# colors=(4 6 1 8 8 6) - Text is colored in the order above.
-colors=(distro)
-
-
-# Text Options
-
-
-# Toggle bold text
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --bold
-bold="on"
-
-# Enable/Disable Underline
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --underline
-underline_enabled="on"
-
-# Underline character
-#
-# Default: '-'
-# Values: 'string'
-# Flag: --underline_char
-underline_char="-"
-
-
-# Color Blocks
-
-
-# Color block range
-# The range of colors to print.
-#
-# Default: '0', '7'
-# Values: 'num'
-# Flag: --block_range
-#
-# Example:
-#
-# Display colors 0-7 in the blocks. (8 colors)
-# neofetch --block_range 0 7
-#
-# Display colors 0-15 in the blocks. (16 colors)
-# neofetch --block_range 0 15
-block_range=(0 15)
-
-# Toggle color blocks
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --color_blocks
-color_blocks="on"
-
-# Color block width in spaces
-#
-# Default: '3'
-# Values: 'num'
-# Flag: --block_width
-block_width=3
-
-# Color block height in lines
-#
-# Default: '1'
-# Values: 'num'
-# Flag: --block_height
-block_height=1
-
-
-# Progress Bars
-
-
-# Bar characters
-#
-# Default: '-', '='
-# Values: 'string', 'string'
-# Flag: --bar_char
-#
-# Example:
-# neofetch --bar_char 'elapsed' 'total'
-# neofetch --bar_char '-' '='
-bar_char_elapsed="-"
-bar_char_total="="
-
-# Toggle Bar border
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --bar_border
-bar_border="on"
-
-# Progress bar length in spaces
-# Number of chars long to make the progress bars.
-#
-# Default: '15'
-# Values: 'num'
-# Flag: --bar_length
-bar_length=15
-
-# Progress bar colors
-# When set to distro, uses your distro's logo colors.
-#
-# Default: 'distro', 'distro'
-# Values: 'distro', 'num'
-# Flag: --bar_colors
-#
-# Example:
-# neofetch --bar_colors 3 4
-# neofetch --bar_colors distro 5
-bar_color_elapsed="distro"
-bar_color_total="distro"
-
-
-# Info display
-# Display a bar with the info.
-#
-# Default: 'off'
-# Values: 'bar', 'infobar', 'barinfo', 'off'
-# Flags: --cpu_display
-# --memory_display
-# --battery_display
-# --disk_display
-#
-# Example:
-# bar: '[---=======]'
-# infobar: 'info [---=======]'
-# barinfo: '[---=======] info'
-# off: 'info'
-cpu_display="off"
-memory_display="off"
-battery_display="off"
-disk_display="off"
-
-
-# Backend Settings
-
-
-# Image backend.
-#
-# Default: 'ascii'
-# Values: 'ascii', 'caca', 'catimg', 'jp2a', 'iterm2', 'off', 'termpix', 'pixterm', 'tycat', 'w3m'
-# Flag: --backend
-image_backend="ascii"
-
-# Image Source
-#
-# Which image or ascii file to display.
-#
-# Default: 'auto'
-# Values: 'auto', 'ascii', 'wallpaper', '/path/to/img', '/path/to/ascii', '/path/to/dir/'
-# Flag: --source
-#
-# NOTE: 'auto' will pick the best image source for whatever image backend is used.
-# In ascii mode, distro ascii art will be used and in an image mode, your
-# wallpaper will be used.
-image_source="auto"
-
-
-# Ascii Options
-
-
-# Ascii distro
-# Which distro's ascii art to display.
-#
-# Default: 'auto'
-# Values: 'auto', 'distro_name'
-# Flag: --ascii_distro
-#
-# NOTE: Arch and Ubuntu have 'old' logo variants.
-# Change this to 'arch_old' or 'ubuntu_old' to use the old logos.
-# NOTE: Ubuntu has flavor variants.
-# Change this to 'Lubuntu', 'Xubuntu', 'Ubuntu-GNOME' or 'Ubuntu-Budgie' to use the flavors.
-# NOTE: Arch, Crux and Gentoo have a smaller logo variant.
-# Change this to 'arch_small', 'crux_small' or 'gentoo_small' to use the small logos.
-ascii_distro="LinuxMint"
-
-# Ascii Colors
-#
-# Default: 'distro'
-# Values: 'distro', 'num' 'num' 'num' 'num' 'num' 'num'
-# Flag: --ascii_colors
-#
-# Example:
-# ascii_colors=(distro) - Ascii is colored based on Distro colors.
-# ascii_colors=(4 6 1 8 8 6) - Ascii is colored using these colors.
-ascii_colors=(distro)
-
-# Bold ascii logo
-# Whether or not to bold the ascii logo.
-#
-# Default: 'on'
-# Values: 'on', 'off'
-# Flag: --ascii_bold
-ascii_bold="on"
-
-
-# Image Options
-
-
-# Image loop
-# Setting this to on will make neofetch redraw the image constantly until
-# Ctrl+C is pressed. This fixes display issues in some terminal emulators.
-#
-# Default: 'off'
-# Values: 'on', 'off'
-# Flag: --loop
-image_loop="off"
-
-# Thumbnail directory
-#
-# Default: '~/.cache/thumbnails/neofetch'
-# Values: 'dir'
-thumbnail_dir="${XDG_CACHE_HOME:-${HOME}/.cache}/thumbnails/neofetch"
-
-# Crop mode
-#
-# Default: 'normal'
-# Values: 'normal', 'fit', 'fill'
-# Flag: --crop_mode
-#
-# See this wiki page to learn about the fit and fill options.
-# https://github.com/dylanaraps/neofetch/wiki/What-is-Waifu-Crop%3F
-crop_mode="normal"
-
-# Crop offset
-# Note: Only affects 'normal' crop mode.
-#
-# Default: 'center'
-# Values: 'northwest', 'north', 'northeast', 'west', 'center'
-# 'east', 'southwest', 'south', 'southeast'
-# Flag: --crop_offset
-crop_offset="center"
-
-# Image size
-# The image is half the terminal width by default.
-#
-# Default: 'auto'
-# Values: 'auto', '00px', '00%', 'none'
-# Flags: --image_size
-# --size
-image_size="auto"
-
-# Gap between image and text
-#
-# Default: '3'
-# Values: 'num', '-num'
-# Flag: --gap
-gap=3
-
-# Image offsets
-# Only works with the w3m backend.
-#
-# Default: '0'
-# Values: 'px'
-# Flags: --xoffset
-# --yoffset
-yoffset=0
-xoffset=0
-
-# Image background color
-# Only works with the w3m backend.
-#
-# Default: ''
-# Values: 'color', 'blue'
-# Flag: --bg_color
-background_color=
-
-
-# Scrot Options
-
-
-# Whether or not to always take a screenshot
-# You can manually take a screenshot with "--scrot" or "-s"
-#
-# Default: 'off'
-# Values: 'on', 'off'
-# Flags: --scrot
-# -s
-scrot="off"
-
-# Screenshot Program
-# Neofetch will automatically use whatever screenshot tool
-# is installed on your system.
-#
-# If 'neofetch -v' says that it couldn't find a screenshot
-# tool or you're using a custom tool then you can change
-# the option below to a custom command.
-#
-# Default: 'auto'
-# Values: 'auto' 'cmd -flags'
-# Flag: --scrot_cmd
-scrot_cmd="auto"
-
-# Screenshot Filename
-# What to name the screenshots
-#
-# Default: 'neofetch-$(date +%F-%I-%M-%S-${RANDOM}).png'
-# Values: 'string'
-# Flag: --scrot_name
-scrot_name="neofetch-$(date +%F-%I-%M-%S-${RANDOM}).png"
-
-# Image upload host
-# Where to upload the image.
-#
-# Default: 'teknik'
-# Values: 'imgur', 'teknik'
-# Flag: --image_host
-#
-# NOTE: If you'd like another image host to be added to Neofetch.
-# Open an issue on github.
-image_host="teknik"
-
-
-# Misc Options
-
-# Stdout mode
-# Turn off all colors and disables image backend (ASCII/Image).
-# Useful for piping into another command.
-# Default: 'off'
-# Values: 'on', 'off'
-stdout="off"
-
-# Config version.
-#
-# NOTE: Don't change this value, neofetch reads this to determine
-# how to handle backwards compatibility.
-config_version="3.4.0"
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index 0fdd8d2f7..000000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-# These are supported funding model platforms
-
-github: [baalajimaestro, raphielscape, mryacha] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
-patreon: # Replace with a single Patreon username
-open_collective: # Replace with a single Open Collective username
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-custom: # Replace with a single custom sponsorship URL
diff --git a/Aptfile b/Aptfile
deleted file mode 100644
index 79d5a38e5..000000000
--- a/Aptfile
+++ /dev/null
@@ -1,3 +0,0 @@
-neofetch
-chromium-chromedriver
-chromium-browser
diff --git a/Dockerfile b/Dockerfile
index 3c2d54247..eeab7209c 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -49,7 +49,9 @@ RUN apk add --no-cache --update \
ffmpeg \
sqlite-dev \
sudo \
- zlib-dev
+ zlib-dev \
+ jpeg-dev \
+ python-dev
RUN python3 -m ensurepip \
@@ -71,13 +73,6 @@ WORKDIR /root/userbot/
#
COPY ./sample_config.env ./userbot.session* ./config.env* /root/userbot/
-#
-# Clone helper scripts
-#
-RUN curl -s https://raw.githubusercontent.com/yshalsager/megadown/master/megadown -o /root/userbot/bin/megadown && sudo chmod a+x /root/userbot/bin/megadown
-RUN curl -s https://raw.githubusercontent.com/yshalsager/cmrudl.py/master/cmrudl.py -o /root/userbot/bin/cmrudl && sudo chmod a+x /root/userbot/bin/cmrudl
-ENV PATH="/root/userbot/bin:$PATH"
-
#
# Install requirements
#
diff --git a/Procfile b/Procfile
deleted file mode 100644
index 0dae77512..000000000
--- a/Procfile
+++ /dev/null
@@ -1 +0,0 @@
-worker: python3 -m userbot
diff --git a/app.json b/app.json
index 34b289d9e..19755a420 100644
--- a/app.json
+++ b/app.json
@@ -54,7 +54,7 @@
"value": "False"
},
"BOTLOG_CHATID": {
- "description": "ChatID of the Log group. Set it to '0' if BOTLOG = False",
+ "description": "ChatID of the Log group. Set it to '0' if BOTLOG = False and/or if LOGSPAMMER = False.",
"value": "0"
},
"CONSOLE_LOGGER_VERBOSE": {
@@ -119,6 +119,7 @@
},
"DEFAULT_BIO": {
"description": "Default profile bio.",
+ "value": "[PM = Report Spam] I ❤ ️@PaperplaneExtended",
"required": false
},
"ALIVE_NAME": {
@@ -128,6 +129,18 @@
"G_DRIVE_CLIENT_SECRET": {
"description": "Enter Your Client Secret for Google Drive.",
"required": false
+ },
+ "G_DRIVE_AUTH_TOKEN_DATA": {
+ "description": "Enter the Google Drive authentication data, as a JSON structure.",
+ "required": false
+ },
+ "WEATHER_DEFCITY": {
+ "description": "Set the default city for the userbot's weather module.",
+ "required": false
+ },
+ "LOGSPAMMER": {
+ "description": "Set this to True in case you want the error logs to be stored in the userbot log group, instead of spitting out the file in the current chat, requires a valid BOTLOG_CHATID to be set.",
+ "value": "True"
}
},
"addons": [
diff --git a/modules b/modules
deleted file mode 100644
index fbb0749a0..000000000
--- a/modules
+++ /dev/null
@@ -1,45 +0,0 @@
-import os
-import subprocess
-import platform
-from userbot import SUDO
-
-def _start_instalation():
- install_with = None
- package_managers = ["pacman", "apt-get", "yum", "brew", "yaourt", "dnf", "homebrew", "eopkg", "snap"]
- if "linux" in str(platform.system()).lower():
- for manager in package_managers:
- try:
- subprocess.check_call(f"which {manager}", shell=True, stderr=subprocess.STDOUT)
- install_package(manager)
- return
- except:
- continue
-
-
-
-def install_package(package_manager):
- packages = []
- to_install = []
- with open("Aptfile") as file:
- for line in file:
- packages.append(line)
-
- for package in packages:
- try:
- subprocess.check_call(f"which {package}", shell=True, stderr=subprocess.STDOUT)
- except:
- to_install.append(package)
-
- if to_install:
- if SUDO:
- subprocess.Popen(f"echo {str(SUDO)} | sudo -S {str(package_manager)}" +
- f" install -y {' '.join(to_install)}", shell=True)
- else:
- subprocess.Popen(f"{str(package_manager)} install -y {' '.join(to_install)}",
- shell=True)
-
-try:
- if not 'heroku' in os.environ['PATH']:
- _start_instalation()
-except:
- _start_instalation()
diff --git a/requirements.txt b/requirements.txt
index 555657154..635c42892 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -33,7 +33,7 @@ requests>=2.18.4
search-engine-parser>=0.4.2
speedtest-cli>=2.0.2
sqlalchemy>=1.2
-telethon>=1.10.3
+telethon>=1.10.6
telethon-session-sqlalchemy>=0.2.6
urbandict>=0.5
wikipedia>=1.4.0
diff --git a/runtime.txt b/runtime.txt
deleted file mode 100644
index 6f651a3b1..000000000
--- a/runtime.txt
+++ /dev/null
@@ -1 +0,0 @@
-python-3.7.3
diff --git a/sample_config.env b/sample_config.env
index 0e89b4d10..78c16fae1 100644
--- a/sample_config.env
+++ b/sample_config.env
@@ -1,99 +1,72 @@
# Remove this line first before doing anything
___________PLOX_______REMOVE_____THIS_____LINE__________=True
-#
-# Get from https://my.telegram.org/
-#
+# Get these from https://my.telegram.org/
API_KEY = "YOUR API KEY"
API_HASH = "YOUR API HASH"
-#
# OpenWeather Map API Key for .weather command
# Get from https://openweathermap.org/
-#
OPEN_WEATHER_MAP_APPID = ""
+WEATHER_DEFCITY = ""
-#
# Location of ChromeDriver for .carbon module
-# Default for Heroku Slugs : "/app/.chromedriver/bin/chromedriver"
-#
+# Example for Linux Machines : "/usr/bin/chromedriver"
CHROME_DRIVER = ""
-#
# Get this value by running python3 string_session.py locally
-#
STRING_SESSION = ""
-#
# Headless GoogleChrome location for .carbon module
-# Default for Heroku Slugs : "/app/.apt/usr/bin/google-chrome"
-#
+# Example for Linux Machines : "/usr/bin/chromium-browser"
GOOGLE_CHROME_BIN = ""
-#
# OCR Space API Key for .ocr command
# Get from https://ocr.space/ocrapi
-#
OCR_SPACE_API_KEY = ""
-#
# remove.bg API Key for .rbg command
# Get from https://www.remove.bg/api
-#
REM_BG_API_KEY = ""
-#
# ChatID for the Log group
# Add a Hypen or a Negative Sign before ID
# This is a integer, Please don't use Strings
-#
-BOTLOG_CHATID = # Chat ID should be integer.
+BOTLOG_CHATID = # this is an integer, please don't use quotes.
-#
# Incase you want to turn off logging, put this to false
-#
BOTLOG = True
-#
+# Set this to True if you want the error logs to be stored in
+# the userbot log, rather than spamming other chats with it.
+# Note that this requires a valid BOTLOG_CHATID to be set.
+LOGSPAMMER = True
+
# If you need Verbosity on the Logging
-#
CONSOLE_LOGGER_VERBOSE = False
-#
# PM Auto-Ban Feature Switch
-#
PM_AUTO_BAN = False
-#
# Custom Default name for .alive
-#
ALIVE_NAME = None
-#
# Your Database URL
# Example: 'postgres://userbot:userbot@localhost:5432/userbot'
-#
DATABASE_URL = ""
-#
# YouTube Data API Key for .yt command
# Get from https://console.cloud.google.com
-#
YOUTUBE_API_KEY = ""
-#
# Country and Time Zone setup for
# .time and .date modules
-#
COUNTRY = ""
-TZ_NUMBER = # this is an integer.
+TZ_NUMBER = # this is an integer, please don't use quotes.
-#
# Google Drive Credentials
# for .gdrive module.
-#
# Get from https://console.cloud.google.com
-#
G_DRIVE_CLIENT_ID = ""
G_DRIVE_CLIENT_SECRET = ""
G_DRIVE_AUTH_TOKEN_DATA = ""
@@ -109,12 +82,11 @@ LASTFM_PASSWORD = "Your last.fm password"
# Bot will add before song name. For last.fm module.
# Example: GitHub: MacTavishAO : Skillet - Feel Invincible
BIO_PREFIX = ""
+
# default bio message
DEFAULT_BIO = ""
-#
# Report or kick some known spammer bots after
# they joins
-#
ANTI_SPAMBOT = False
ANTI_SPAMBOT_SHOUT = False
diff --git a/userbot/__init__.py b/userbot/__init__.py
index 3ed93385c..ad293982c 100644
--- a/userbot/__init__.py
+++ b/userbot/__init__.py
@@ -11,7 +11,7 @@
from logging import basicConfig, getLogger, INFO, DEBUG
from distutils.util import strtobool as sb
-import pylast
+from pylast import LastFMNetwork, md5
from pySmartDL import SmartDL
from dotenv import load_dotenv
from requests import get
@@ -35,7 +35,7 @@
if version_info[0] < 3 or version_info[1] < 6:
LOGS.info("You MUST have a python version of at least 3.6."
- "Multiple features depend on this. Bot quitting.")
+ "Multiple features depend on this. Bot quitting.")
quit(1)
# Check if the config was edited by using the already used variable.
@@ -56,11 +56,12 @@
# Userbot Session String
STRING_SESSION = os.environ.get("STRING_SESSION", None)
-# Logging channel/group configuration.
+# Logging channel/group ID configuration.
BOTLOG_CHATID = int(os.environ.get("BOTLOG_CHATID", None))
# Userbot logging feature switch.
BOTLOG = sb(os.environ.get("BOTLOG", "False"))
+LOGSPAMMER = sb(os.environ.get("LOGSPAMMER", "False"))
# Bleep Blop, this is a bot ;)
PM_AUTO_BAN = sb(os.environ.get("PM_AUTO_BAN", "False"))
@@ -83,10 +84,10 @@
# OpenWeatherMap API Key
OPEN_WEATHER_MAP_APPID = os.environ.get("OPEN_WEATHER_MAP_APPID", None)
+WEATHER_DEFCITY = os.environ.get("WEATHER_DEFCITY", None)
# Anti Spambot Config
ANTI_SPAMBOT = sb(os.environ.get("ANTI_SPAMBOT", "False"))
-
ANTI_SPAMBOT_SHOUT = sb(os.environ.get("ANTI_SPAMBOT_SHOUT", "False"))
# Youtube API key
@@ -97,7 +98,6 @@
# Time & Date - Country and Time Zone
COUNTRY = str(os.environ.get("COUNTRY", ""))
-
TZ_NUMBER = int(os.environ.get("TZ_NUMBER", 1))
# Clean Welcome
@@ -111,12 +111,12 @@
LASTFM_SECRET = os.environ.get("LASTFM_SECRET", None)
LASTFM_USERNAME = os.environ.get("LASTFM_USERNAME", None)
LASTFM_PASSWORD_PLAIN = os.environ.get("LASTFM_PASSWORD", None)
-LASTFM_PASS = pylast.md5(LASTFM_PASSWORD_PLAIN)
-if not LASTFM_USERNAME == "None":
- lastfm = pylast.LastFMNetwork(api_key=LASTFM_API,
- api_secret=LASTFM_SECRET,
- username=LASTFM_USERNAME,
- password_hash=LASTFM_PASS)
+LASTFM_PASS = md5(LASTFM_PASSWORD_PLAIN)
+if LASTFM_API and LASTFM_SECRET and LASTFM_USERNAME and LASTFM_PASS:
+ lastfm = LastFMNetwork(api_key=LASTFM_API,
+ api_secret=LASTFM_SECRET,
+ username=LASTFM_USERNAME,
+ password_hash=LASTFM_PASS)
else:
lastfm = None
@@ -155,12 +155,21 @@
async def check_botlog_chatid():
- if not BOTLOG_CHATID:
+ if not BOTLOG_CHATID and LOGSPAMMER:
LOGS.info(
- "You must set up the BOTLOG_CHATID variable in the config.env or environment variables, "
- "many critical features depend on it. KTHXBye.")
+ "You must set up the BOTLOG_CHATID variable in the config.env or environment variables, for the private error log storage to work."
+ )
quit(1)
+ elif not BOTLOG_CHATID and BOTLOG:
+ LOGS.info(
+ "You must set up the BOTLOG_CHATID variable in the config.env or environment variables, for the userbot logging feature to work."
+ )
+ quit(1)
+
+ elif not BOTLOG or not LOGSPAMMER:
+ return
+
entity = await bot.get_entity(BOTLOG_CHATID)
if entity.default_banned_rights.send_messages:
LOGS.info(
@@ -168,6 +177,7 @@ async def check_botlog_chatid():
"group. Check if you typed the Chat ID correctly.")
quit(1)
+
with bot:
try:
bot.loop.run_until_complete(check_botlog_chatid())
diff --git a/userbot/events.py b/userbot/events.py
index cf4f559c9..42a9cafb3 100644
--- a/userbot/events.py
+++ b/userbot/events.py
@@ -6,18 +6,16 @@
""" Userbot module for managing events.
One of the main components of the userbot. """
-from telethon import events
-
-from asyncio import subprocess as asyncsub
-from asyncio import create_subprocess_shell as asyncsubshell
-
import sys
+from asyncio import create_subprocess_shell as asyncsubshell
+from asyncio import subprocess as asyncsub
from os import remove
+from time import gmtime, strftime
+from traceback import format_exc
-from userbot import bot, BOTLOG_CHATID
+from telethon import events
-from traceback import format_exc
-from time import gmtime, strftime
+from userbot import bot, BOTLOG_CHATID, LOGSPAMMER
def register(**args):
@@ -25,8 +23,10 @@ def register(**args):
pattern = args.get('pattern', None)
disable_edited = args.get('disable_edited', False)
ignore_unsafe = args.get('ignore_unsafe', False)
- forwards = args.get('forwards', False)
unsafe_pattern = r'^[^/!#@\$A-Za-z]'
+ groups_only = args.get('groups_only', False)
+ trigger_on_fwd = args.get('trigger_on_fwd', False)
+ disable_errors = args.get('disable_errors', False)
if pattern is not None and not pattern.startswith('(?i)'):
args['pattern'] = '(?i)' + pattern
@@ -37,77 +37,112 @@ def register(**args):
if "ignore_unsafe" in args:
del args['ignore_unsafe']
- if "forwards" in args:
- del args['forwards']
+ if "groups_only" in args:
+ del args['groups_only']
+
+ if "disable_errors" in args:
+ del args['disable_errors']
+
+ if "trigger_on_fwd" in args:
+ del args['trigger_on_fwd']
if pattern:
if not ignore_unsafe:
args['pattern'] = pattern.replace('^.', unsafe_pattern, 1)
def decorator(func):
+ async def wrapper(check):
+ if not LOGSPAMMER:
+ send_to = check.chat_id
+ else:
+ send_to = BOTLOG_CHATID
+
+ if not trigger_on_fwd and check.fwd_from:
+ return
+
+ if groups_only and not check.is_group:
+ await check.respond("`I don't think this is a group.`")
+ return
+
+ try:
+ await func(check)
+
+ # Thanks to @kandnub for this HACK.
+ # Raise StopPropagation to Raise StopPropagation
+ # This needed for AFK to working properly
+
+ except events.StopPropagation:
+ raise events.StopPropagation
+ # This is a gay exception and must be passed out. So that it doesnt spam chats
+ except KeyboardInterrupt:
+ pass
+ except BaseException:
+
+ # Check if we have to disable it.
+ # If not silence the log spam on the console,
+ # with a dumb except.
+
+ if not disable_errors:
+ date = strftime("%Y-%m-%d %H:%M:%S", gmtime())
+
+ text = "**USERBOT ERROR REPORT**\n"
+ link = "[PaperplaneExtended Support Chat](https://t.me/PaperplaneExtendedSupport)"
+ text += "If you want to, you can report it"
+ text += f"- just forward this message to {link}.\n"
+ text += "Nothing is logged except the fact of error and date\n"
+
+ ftext = "========== DISCLAIMER =========="
+ ftext += "\nThis file uploaded ONLY here,"
+ ftext += "\nwe logged only fact of error and date,"
+ ftext += "\nwe respect your privacy,"
+ ftext += "\nyou may not report this error if you've"
+ ftext += "\nany confidential data here, no one will see your data\n"
+ ftext += "================================\n\n"
+ ftext += "--------BEGIN USERBOT TRACEBACK LOG--------\n"
+ ftext += "\nDate: " + date
+ ftext += "\nChat ID: " + str(check.chat_id)
+ ftext += "\nSender ID: " + str(check.sender_id)
+ ftext += "\n\nEvent Trigger:\n"
+ ftext += str(check.text)
+ ftext += "\n\nTraceback info:\n"
+ ftext += str(format_exc())
+ ftext += "\n\nError text:\n"
+ ftext += str(sys.exc_info()[1])
+ ftext += "\n\n--------END USERBOT TRACEBACK LOG--------"
+
+ command = "git log --pretty=format:\"%an: %s\" -10"
+
+ ftext += "\n\n\nLast 10 commits:\n"
+
+ process = await asyncsubshell(command,
+ stdout=asyncsub.PIPE,
+ stderr=asyncsub.PIPE)
+ stdout, stderr = await process.communicate()
+ result = str(stdout.decode().strip()) \
+ + str(stderr.decode().strip())
+
+ ftext += result
+
+ file = open("error.log", "w+")
+ file.write(ftext)
+ file.close()
+
+ if LOGSPAMMER:
+ await check.client.respond(
+ "`Sorry, my userbot has crashed.\
+ \nThe error logs are stored in the userbot's log chat.`"
+ )
+
+ await check.client.send_file(send_to,
+ "error.log",
+ caption=text)
+ remove("error.log")
+ else:
+ pass
+
if not disable_edited:
- bot.add_event_handler(func, events.MessageEdited(**args))
- bot.add_event_handler(func, events.NewMessage(**args))
- return func
+ bot.add_event_handler(wrapper, events.MessageEdited(**args))
+ bot.add_event_handler(wrapper, events.NewMessage(**args))
+ return wrapper
return decorator
-
-
-def errors_handler(func):
- async def wrapper(errors):
- try:
- await func(errors)
- except BaseException:
- date = strftime("%Y-%m-%d %H:%M:%S", gmtime())
-
- text = "**USERBOT CRASH REPORT**\n"
- link = "[PaperplaneExtended Support Chat](https://t.me/PaperplaneExtendedSupport)"
- text += "If you wanna you can report it"
- text += f"- just forward this message to {link}.\n"
- text += "Nothing is logged except the fact of error and date\n"
-
- ftext = "========== DISCLAIMER =========="
- ftext += "\nThis file uploaded ONLY here,"
- ftext += "\nwe logged only fact of error and date,"
- ftext += "\nwe respect your privacy,"
- ftext += "\nyou may not report this error if you've"
- ftext += "\nany confidential data here, no one will see your data\n"
- ftext += "================================\n\n"
- ftext += "--------BEGIN USERBOT TRACEBACK LOG--------"
- ftext += "\nDate: " + date
- ftext += "\nGroup ID: " + str(errors.chat_id)
- ftext += "\nSender ID: " + str(errors.sender_id)
- ftext += "\n\nEvent Trigger:\n"
- ftext += str(errors.text)
- ftext += "\n\nTraceback info:\n"
- ftext += str(format_exc())
- ftext += "\n\nError text:\n"
- ftext += str(sys.exc_info()[1])
- ftext += "\n\n--------END USERBOT TRACEBACK LOG--------"
-
- command = "git log --pretty=format:\"%an: %s\" -5"
-
- ftext += "\n\n\nLast 5 commits:\n"
-
- process = await asyncsubshell(command,
- stdout=asyncsub.PIPE,
- stderr=asyncsub.PIPE)
- stdout, stderr = await process.communicate()
- result = str(stdout.decode().strip()) \
- + str(stderr.decode().strip())
-
- ftext += result
-
- file = open("error.log", "w+")
- file.write(ftext)
- file.close()
-
- await errors.client.send_file(
- BOTLOG_CHATID,
- "error.log",
- caption=text,
- )
- remove("error.log")
- return
-
- return wrapper
diff --git a/userbot/modules/admin.py b/userbot/modules/admin.py
index 282feed53..b5a1717b3 100644
--- a/userbot/modules/admin.py
+++ b/userbot/modules/admin.py
@@ -18,12 +18,13 @@
EditBannedRequest,
EditPhotoRequest)
from telethon.tl.functions.messages import UpdatePinnedMessageRequest
-from telethon.tl.types import (ChannelParticipantsAdmins, ChatAdminRights,
- ChatBannedRights, MessageEntityMentionName,
- MessageMediaPhoto)
+from telethon.tl.types import (PeerChannel, ChannelParticipantsAdmins,
+ ChatAdminRights, ChatBannedRights,
+ MessageEntityMentionName, MessageMediaPhoto,
+ ChannelParticipantsBots)
from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP, bot
-from userbot.events import register, errors_handler
+from userbot.events import register
# =================== CONSTANT ===================
PP_TOO_SMOL = "`The image is too small`"
@@ -67,8 +68,7 @@
# ================================================
-@register(outgoing=True, pattern="^.setgpic$")
-@errors_handler
+@register(outgoing=True, pattern="^.setgpic$", groups_only=True)
async def set_group_photo(gpic):
""" For .setgpic command, changes the picture of a group """
if not gpic.is_group:
@@ -105,8 +105,7 @@ async def set_group_photo(gpic):
await gpic.edit(PP_ERROR)
-@register(outgoing=True, pattern="^.promote(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.promote(?: |$)(.*)", groups_only=True)
async def promote(promt):
""" For .promote command, promotes the replied/tagged person """
# Get targeted chat
@@ -130,7 +129,8 @@ async def promote(promt):
await promt.edit("`Promoting...`")
user, rank = await get_user_from_event(promt)
if not rank:
- rank = "admeme" # Just in case.
+ # Just in case.
+ rank = "admeme"
if user:
pass
else:
@@ -156,8 +156,7 @@ async def promote(promt):
f"CHAT: {promt.chat.title}(`{promt.chat_id}`)")
-@register(outgoing=True, pattern="^.demote(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.demote(?: |$)(.*)", groups_only=True)
async def demote(dmod):
""" For .demote command, demotes the replied/tagged person """
# Admin right check
@@ -206,8 +205,7 @@ async def demote(dmod):
f"CHAT: {dmod.chat.title}(`{dmod.chat_id}`)")
-@register(outgoing=True, pattern="^.ban(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.ban(?: |$)(.*)", groups_only=True)
async def ban(bon):
""" For .ban command, bans the replied/tagged person """
# Here laying the sanity check
@@ -248,9 +246,12 @@ async def ban(bon):
# is done gracefully
# Shout out the ID, so that fedadmins can fban later
if reason:
- await bon.edit(f"`{str(user.id)}` was banned !!\nReason: {reason}")
+ await bon.edit(f"{user.first_name} was banned !!\
+ \nID: `{str(user.id)}`\
+ \nReason: {reason}")
else:
- await bon.edit(f"`{str(user.id)}` was banned !!")
+ await bon.edit(f"{user.first_name} was banned !!\
+ \nID: `{str(user.id)}`")
# Announce to the logging group if we have banned the person
# successfully!
if BOTLOG:
@@ -260,8 +261,7 @@ async def ban(bon):
f"CHAT: {bon.chat.title}(`{bon.chat_id}`)")
-@register(outgoing=True, pattern="^.unban(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.unban(?: |$)(.*)", groups_only=True)
async def nothanos(unbon):
""" For .unban command, unbans the replied/tagged person """
# Here laying the sanity check
@@ -298,8 +298,7 @@ async def nothanos(unbon):
await unbon.edit("`Uh oh my unban logic broke!`")
-@register(outgoing=True, pattern="^.mute(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.mute(?: |$)(.*)", groups_only=True)
async def spider(spdr):
"""
This function is basically muting peeps
@@ -359,8 +358,7 @@ async def spider(spdr):
return await spdr.edit("`Uh oh my mute logic broke!`")
-@register(outgoing=True, pattern="^.unmute(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.unmute(?: |$)(.*)", groups_only=True)
async def unmoot(unmot):
""" For .unmute command, unmute the replied/tagged person """
# Admin or creator check
@@ -408,8 +406,7 @@ async def unmoot(unmot):
f"CHAT: {unmot.chat.title}(`{unmot.chat_id}`)")
-@register(incoming=True)
-@errors_handler
+@register(incoming=True, disable_edited=True)
async def muter(moot):
""" Used for deleting the messages of muted people """
try:
@@ -440,8 +437,7 @@ async def muter(moot):
await moot.delete()
-@register(outgoing=True, pattern="^.ungmute(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.ungmute(?: |$)(.*)", groups_only=True)
async def ungmoot(un_gmute):
""" For .ungmute command, ungmutes the target in the userbot """
# Admin or creator check
@@ -484,8 +480,7 @@ async def ungmoot(un_gmute):
f"CHAT: {un_gmute.chat.title}(`{un_gmute.chat_id}`)")
-@register(outgoing=True, pattern="^.gmute(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.gmute(?: |$)(.*)", groups_only=True)
async def gspider(gspdr):
""" For .gmute command, globally mutes the replied/tagged person """
# Admin or creator check
@@ -529,14 +524,13 @@ async def gspider(gspdr):
f"CHAT: {gspdr.chat.title}(`{gspdr.chat_id}`)")
-@register(outgoing=True, pattern="^.delusers(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.zombies(?: |$)(.*)", groups_only=True)
async def rm_deletedacc(show):
""" For .delusers command, list all the ghost/deleted accounts in a chat. """
if not show.is_group:
await show.edit("`I don't think this is a group.`")
return
- con = show.pattern_match.group(1)
+ con = show.pattern_match.group(1).lower()
del_u = 0
del_status = "`No deleted accounts found, Group is cleaned as Hell`"
@@ -601,8 +595,7 @@ async def rm_deletedacc(show):
\nCHAT: {show.chat.title}(`{show.chat_id}`)")
-@register(outgoing=True, pattern="^.admins$")
-@errors_handler
+@register(outgoing=True, pattern="^.admins$", groups_only=True)
async def get_admin(show):
""" For .admins command, list all of the admins of the chat. """
info = await show.client.get_entity(show.chat_id)
@@ -619,11 +612,62 @@ async def get_admin(show):
mentions += f"\nDeleted Account {user.id}
"
except ChatAdminRequiredError as err:
mentions += " " + str(err) + "\n"
- await show.edit(mentions, parse_mode="html")
+ try:
+ await show.edit(mentions, parse_mode="html")
+ except MessageTooLongError:
+ await show.edit(
+ "Damn, too many admins here. Uploading admin list as file.")
+ file = open("adminlist.txt", "w+")
+ file.write(mentions)
+ file.close()
+ await show.client.send_file(
+ show.chat_id,
+ "adminlist.txt",
+ caption='Admins in {}'.format(title),
+ reply_to=show.id,
+ )
+ remove("adminlist.txt")
+
+
+@register(outgoing=True, pattern="^.bots$", groups_only=True)
+async def get_bots(show):
+ """ For .bots command, list all of the bots of the chat. """
+ info = await show.client.get_entity(show.chat_id)
+ title = info.title if info.title else "this chat"
+ mentions = f'Bots in {title}:\n'
+ try:
+ if isinstance(message.to_id, PeerChat):
+ await show.edit("`I heard that only Supergroups can have bots.`")
+ return
+ else:
+ async for user in show.client.iter_participants(
+ show.chat_id, filter=ChannelParticipantsBots):
+ if not user.deleted:
+ link = f"{user.first_name}"
+ userid = f"{user.id}
"
+ mentions += f"\n{link} {userid}"
+ else:
+ mentions += f"\nDeleted Bot {user.id}
"
+ except ChatAdminRequiredError as err:
+ mentions += " " + str(err) + "\n"
+ try:
+ await show.edit(mentions, parse_mode="html")
+ except MessageTooLongError:
+ await show.edit(
+ "Damn, too many bots here. Uploading bots list as file.")
+ file = open("botlist.txt", "w+")
+ file.write(mentions)
+ file.close()
+ await show.client.send_file(
+ show.chat_id,
+ "botlist.txt",
+ caption='Bots in {}'.format(title),
+ reply_to=show.id,
+ )
+ remove("botlist.txt")
-@register(outgoing=True, pattern="^.pin(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.pin(?: |$)(.*)", groups_only=True)
async def pin(msg):
""" For .pin command, pins the replied/tagged message on the top the chat. """
# Admin or creator check
@@ -668,8 +712,7 @@ async def pin(msg):
f"LOUD: {not is_silent}")
-@register(outgoing=True, pattern="^.kick(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.kick(?: |$)(.*)", groups_only=True)
async def kick(usr):
""" For .kick command, kicks the replied/tagged person from the group. """
# Admin or creator check
@@ -693,7 +736,7 @@ async def kick(usr):
await usr.client.kick_participant(usr.chat_id, user.id)
await sleep(.5)
except Exception as e:
- await usr.edit(NO_PERM + f"\n{str(e)}")
+ await usr.edit(NO_PERM)
return
if reason:
@@ -711,8 +754,7 @@ async def kick(usr):
f"CHAT: {usr.chat.title}(`{usr.chat_id}`)\n")
-@register(outgoing=True, pattern="^.users ?(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.users ?(.*)", groups_only=True)
async def get_users(show):
""" For .users command, list all of the users in a chat. """
info = await show.client.get_entity(show.chat_id)
@@ -754,13 +796,13 @@ async def get_users(show):
async def get_user_from_event(event):
""" Get the user from argument or replied message. """
- args = event.pattern_match.group(1).split(' ', 1)
+ args = event.pattern_match.group(1).split(':', 1)
extra = None
if event.reply_to_msg_id and not len(args) == 2:
previous_message = await event.get_reply_message()
user_obj = await event.client.get_entity(previous_message.from_id)
extra = event.pattern_match.group(1)
- elif args:
+ elif len(args[0]) > 0:
user = args[0]
if len(args) == 2:
extra = args[1]
@@ -804,28 +846,30 @@ async def get_user_from_id(user, event):
CMD_HELP.update({
"admin":
- ".promote \
+ ".promote : (or) reply to a message with .promote \
\nUsage: Provides admin rights to the person in the chat.\
-\n\n.demote \
+\n\n.demote (or) reply to a message with .demote\
\nUsage: Revokes the person's admin permissions in the chat.\
-\n\n.ban \
+\n\n.ban : (or) reply to a message with .ban \
\nUsage: Bans the person off your chat.\
-\n\n.unban \
+\n\n.unban (or) reply to a message with .unban\
\nUsage: Removes the ban from the person in the chat.\
-\n\n.mute \
+\n\n.mute : reply to a message with .mute \
\nUsage: Mutes the person in the chat, works on admins too.\
-\n\n.unmute \
+\n\n.unmute (or) reply to a message with .unmute\
\nUsage: Removes the person from the muted list.\
-\n\n.gmute \
+\n\n.gmute : (or) reply to a message with .gmute \
\nUsage: Mutes the person in all groups you have in common with them.\
-\n\n.ungmute \
-\nUsage: Reply someone's message with .ungmute to remove them from the gmuted list.\
+\n\n.ungmute (or) reply to a message with .ungmute\
+\nUsage: Removes the person from the global mute list.\
\n\n.delusers\
\nUsage: Searches for deleted accounts in a group. Use .delusers clean to remove deleted accounts from the group.\
\n\n.admins\
\nUsage: Retrieves a list of admins in the chat.\
-\n\n.users or .users \
+\n\n.bots\
+\nUsage: Retrieves a list of bots in the chat.\
+\n\n.users or .users \
\nUsage: Retrieves all (or queried) users in the chat.\
-\n\n.setgppic \
+\n\n.setgpic \
\nUsage: Changes the group's display picture."
})
diff --git a/userbot/modules/afk.py b/userbot/modules/afk.py
index 4d8e48aae..5e155beee 100644
--- a/userbot/modules/afk.py
+++ b/userbot/modules/afk.py
@@ -12,7 +12,7 @@
from userbot import (AFKREASON, COUNT_MSG, CMD_HELP, ISAFK, BOTLOG,
BOTLOG_CHATID, USERS, PM_AUTO_BAN)
-from userbot.events import register, errors_handler
+from userbot.events import register
# ========================= CONSTANTS ============================
AFKSTR = [
@@ -44,7 +44,6 @@
@register(incoming=True, disable_edited=True)
-@errors_handler
async def mention_afk(mention):
""" This function takes care of notifying the people who mention you that you are AFK."""
global COUNT_MSG
@@ -74,8 +73,7 @@ async def mention_afk(mention):
COUNT_MSG = COUNT_MSG + 1
-@register(incoming=True)
-@errors_handler
+@register(incoming=True, disable_errors=True)
async def afk_on_pm(sender):
""" Function which informs people that you are AFK in PM """
global ISAFK
@@ -94,7 +92,8 @@ async def afk_on_pm(sender):
if apprv and ISAFK:
if sender.sender_id not in USERS:
if AFKREASON:
- await sender.reply(f"I'm AFK: `{AFKREASON}`")
+ await sender.reply(f"I'm AFK right now.\
+ \nReason: `{AFKREASON}`")
else:
await sender.reply(str(choice(AFKSTR)))
USERS.update({sender.sender_id: 1})
@@ -102,7 +101,8 @@ async def afk_on_pm(sender):
elif apprv and sender.sender_id in USERS:
if USERS[sender.sender_id] % randint(2, 4) == 0:
if AFKREASON:
- await sender.reply(f"I'm still AFK: `{AFKREASON}`")
+ await sender.reply(f"I'm still AFK.\
+ \nReason: `{AFKREASON}`")
else:
await sender.reply(str(choice(AFKSTR)))
USERS[sender.sender_id] = USERS[sender.sender_id] + 1
@@ -112,7 +112,7 @@ async def afk_on_pm(sender):
COUNT_MSG = COUNT_MSG + 1
-@register(outgoing=True, pattern="^.afk(?: |$)(.*)")
+@register(outgoing=True, pattern="^.afk(?: |$)(.*)", disable_errors=True)
async def set_afk(afk_e):
""" For .afk command, allows you to inform people that you are afk when they message you """
message = afk_e.text
@@ -132,7 +132,6 @@ async def set_afk(afk_e):
@register(outgoing=True)
-@errors_handler
async def type_afk_is_not_true(notafk):
""" This sets your status as not afk automatically when you write something while being afk """
global ISAFK
diff --git a/userbot/modules/android.py b/userbot/modules/android.py
index d62e6fbc1..8d3e432b4 100644
--- a/userbot/modules/android.py
+++ b/userbot/modules/android.py
@@ -10,7 +10,7 @@
from bs4 import BeautifulSoup
from userbot import CMD_HELP
-from userbot.events import register, errors_handler
+from userbot.events import register
GITHUB = 'https://github.com'
DEVICES_DATA = 'https://raw.githubusercontent.com/androidtrackers/' \
@@ -39,7 +39,6 @@ async def magisk(request):
await request.edit(releases)
@register(outgoing=True, pattern=r"^.device(?: |$)(\S*)")
-@errors_handler
async def device_info(request):
""" get android device basic info from its codename """
textx = await request.get_reply_message()
@@ -71,7 +70,6 @@ async def device_info(request):
@register(outgoing=True, pattern=r"^.codename(?: |)([\S]*)(?: |)([\s\S]*)")
-@errors_handler
async def codename_info(request):
""" search for android codename """
textx = await request.get_reply_message()
@@ -107,7 +105,6 @@ async def codename_info(request):
@register(outgoing=True, pattern=r"^.specs(?: |)([\S]*)(?: |)([\s\S]*)")
-@errors_handler
async def devices_specifications(request):
""" Mobile devices specifications """
textx = await request.get_reply_message()
@@ -161,7 +158,6 @@ async def devices_specifications(request):
@register(outgoing=True, pattern=r"^.twrp(?: |$)(\S*)")
-@errors_handler
async def twrp(request):
""" get android device twrp """
textx = await request.get_reply_message()
diff --git a/userbot/modules/anti_spambot.py b/userbot/modules/anti_spambot.py
index af6c7b9b1..6e084aa55 100644
--- a/userbot/modules/anti_spambot.py
+++ b/userbot/modules/anti_spambot.py
@@ -12,11 +12,9 @@
from telethon.tl.types import ChannelParticipantsAdmins, Message
from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP, ANTI_SPAMBOT, ANTI_SPAMBOT_SHOUT, bot
-from userbot.events import errors_handler
@bot.on(ChatAction)
-@errors_handler
async def ANTI_SPAMBOT(welcm):
try:
''' Ban a recently joined user if it
diff --git a/userbot/modules/aria.py b/userbot/modules/aria.py
index c31ef8cf0..cac30cec3 100644
--- a/userbot/modules/aria.py
+++ b/userbot/modules/aria.py
@@ -1,22 +1,34 @@
-#This Lit Module By:- @Zero_cool7870 Sar
-#Special thanks to @spechide who modified this aria
+# Copyright (C) 2019 The Raphielscape Company LLC.
+#
+# Licensed under the Raphielscape Public License, Version 1.c (the "License");
+# you may not use this file except in compliance with the License.
import aria2p
from asyncio import sleep
from os import system
from userbot import LOGS, CMD_HELP
-from userbot.events import register, errors_handler
+from userbot.events import register
+from requests import get
-cmd = "aria2c \
+# Get best trackers for improved download speeds, thanks K-E-N-W-A-Y.
+trackers_list = get(
+ 'https://raw.githubusercontent.com/ngosang/trackerslist/master/trackers_best.txt'
+).text.replace('\n\n', ',')
+trackers = f"[{trackers_list}]"
+
+cmd = f"aria2c \
--enable-rpc \
--rpc-listen-all=false \
--rpc-listen-port 6800 \
--max-connection-per-server=10 \
--rpc-max-request-size=1024M \
--seed-time=0.01 \
+--max-upload-limit=5K \
+--max-concurrent-downloads=5 \
--min-split-size=10M \
--follow-torrent=mem \
--split=10 \
+--bt-tracker={trackers} \
--daemon=true \
--allow-overwrite=true"
@@ -27,7 +39,6 @@
@register(outgoing=True, pattern="^.amag(?: |$)(.*)")
-@errors_handler
async def magnet_download(event):
magnet_uri = event.pattern_match.group(1)
# Add Magnet URI Into Queue
@@ -45,7 +56,6 @@ async def magnet_download(event):
@register(outgoing=True, pattern="^.ator(?: |$)(.*)")
-@errors_handler
async def torrent_download(event):
torrent_file_path = event.pattern_match.group(1)
# Add Torrent Into Queue
@@ -62,7 +72,6 @@ async def torrent_download(event):
@register(outgoing=True, pattern="^.aurl(?: |$)(.*)")
-@errors_handler
async def magnet_download(event):
uri = [event.pattern_match.group(1)]
try: # Add URL Into Queue
@@ -80,7 +89,6 @@ async def magnet_download(event):
@register(outgoing=True, pattern="^.aclear(?: |$)(.*)")
-@errors_handler
async def remove_all(event):
try:
removed = aria2.remove_all(force=True)
@@ -96,7 +104,6 @@ async def remove_all(event):
@register(outgoing=True, pattern="^.apause(?: |$)(.*)")
-@errors_handler
async def pause_all(event):
# Pause ALL Currently Running Downloads.
paused = aria2.pause_all(force=True)
@@ -107,7 +114,6 @@ async def pause_all(event):
@register(outgoing=True, pattern="^.aresume(?: |$)(.*)")
-@errors_handler
async def resume_all(event):
resumed = aria2.resume_all()
await event.edit("`Resuming downloads...`")
@@ -118,7 +124,6 @@ async def resume_all(event):
@register(outgoing=True, pattern="^.ashow(?: |$)(.*)")
-@errors_handler
async def show_all(event):
output = "output.txt"
downloads = aria2.get_downloads()
@@ -163,7 +168,7 @@ async def check_progress_for_dl(gid, event, previous):
file = aria2.get_download(gid)
complete = file.is_complete
try:
- if not file.error_message:
+ if not complete and not file.error_message:
msg = f"\nDownloading File: `{file.name}`"
msg += f"\nSpeed: {file.download_speed_string()}"
msg += f"\nProgress: {file.progress_string()}"
@@ -181,10 +186,11 @@ async def check_progress_for_dl(gid, event, previous):
file = aria2.get_download(gid)
complete = file.is_complete
if complete:
- await event.edit(f"File Downloaded Successfully:`{file.name}`")
+ await event.edit(f"File Downloaded Successfully: `{file.name}`"
+ )
return False
except Exception as e:
- if "not found" in str(e) or "'file'" in str(e):
+ if " not found" in str(e) or "'file'" in str(e):
await event.edit("Download Canceled :\n`{}`".format(file.name))
await sleep(2.5)
await event.delete()
diff --git a/userbot/modules/chat.py b/userbot/modules/chat.py
index aec65d1b5..c1ab539f1 100644
--- a/userbot/modules/chat.py
+++ b/userbot/modules/chat.py
@@ -4,14 +4,13 @@
# you may not use this file except in compliance with the License.
""" Userbot module containing userid, chatid and log commands"""
-from time import sleep
+from asyncio import sleep
from userbot import CMD_HELP, BOTLOG, BOTLOG_CHATID, bot
-from userbot.events import register, errors_handler
+from userbot.events import register
from userbot.modules.admin import get_user_from_event
@register(outgoing=True, pattern="^.userid$")
-@errors_handler
async def useridgetter(target):
""" For .userid command, returns the ID of the target user. """
message = await target.get_reply_message()
@@ -32,13 +31,11 @@ async def useridgetter(target):
name, user_id))
-@register(outgoing=True, pattern="^.mention(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.link(?: |$)(.*)")
async def permalink(mention):
- """ For .mention command, generates a link to the user's PM with a custom text. """
+ """ For .link command, generates a link to the user's PM with a custom text. """
user, custom = await get_user_from_event(mention)
if not user:
- await mention.edit("`User not found.`")
return
if custom:
await mention.edit(f"[{custom}](tg://user?id={user.id})")
@@ -49,14 +46,12 @@ async def permalink(mention):
@register(outgoing=True, pattern="^.chatid$")
-@errors_handler
async def chatidgetter(chat):
""" For .chatid, returns the ID of the chat you are in at that moment. """
await chat.edit("Chat ID: `" + str(chat.chat_id) + "`")
@register(outgoing=True, pattern=r"^.log(?: |$)([\s\S]*)")
-@errors_handler
async def log(log_text):
""" For .log command, forwards a message or the command argument to the bot logs group """
if BOTLOG:
@@ -73,12 +68,11 @@ async def log(log_text):
await log_text.edit("`Logged Successfully`")
else:
await log_text.edit("`This feature requires Logging to be enabled!`")
- sleep(2)
+ await sleep(2)
await log_text.delete()
@register(outgoing=True, pattern="^.kickme$")
-@errors_handler
async def kickme(leave):
""" Basically it's .kickme command """
await leave.edit("Nope, no, no, I go away")
@@ -86,7 +80,6 @@ async def kickme(leave):
@register(outgoing=True, pattern="^.unmutechat$")
-@errors_handler
async def unmute_chat(unm_e):
""" For .unmutechat command, unmute a muted chat. """
try:
@@ -96,12 +89,11 @@ async def unmute_chat(unm_e):
return
unkread(str(unm_e.chat_id))
await unm_e.edit("```Unmuted this chat Successfully```")
- sleep(2)
+ await sleep(2)
await unm_e.delete()
@register(outgoing=True, pattern="^.mutechat$")
-@errors_handler
async def mute_chat(mute_e):
""" For .mutechat command, mute any chat. """
try:
@@ -112,7 +104,7 @@ async def mute_chat(mute_e):
await mute_e.edit(str(mute_e.chat_id))
kread(str(mute_e.chat_id))
await mute_e.edit("`Shush! This chat will be silenced!`")
- sleep(2)
+ await sleep(2)
await mute_e.delete()
if BOTLOG:
await mute_e.client.send_message(
@@ -120,8 +112,7 @@ async def mute_chat(mute_e):
str(mute_e.chat_id) + " was silenced.")
-@register(incoming=True)
-@errors_handler
+@register(incoming=True, disable_errors=True)
async def keep_read(message):
""" The mute logic. """
try:
@@ -135,6 +126,34 @@ async def keep_read(message):
await message.client.send_read_acknowledge(message.chat_id)
+# Regex-Ninja module by @Kandnub
+regexNinja = False
+
+
+@register(outgoing=True, pattern="^s/")
+async def sedNinja(event):
+ """For regex-ninja module, auto delete command starting with s/"""
+ if regexNinja:
+ await sleep(.5)
+ await event.delete()
+
+
+@register(outgoing=True, pattern="^.regexninja (on|off)$")
+async def sedNinjaToggle(event):
+ """ Enables or disables the regex ninja module. """
+ global regexNinja
+ if event.pattern_match.group(1) == "on":
+ regexNinja = True
+ await event.edit("`Successfully enabled ninja mode for Regexbot.`")
+ await sleep(1)
+ await event.delete()
+ elif event.pattern_match.group(1) == "off":
+ regexNinja = False
+ await event.edit("`Successfully disabled ninja mode for Regexbot.`")
+ await sleep(1)
+ await event.delete()
+
+
CMD_HELP.update({
"chat":
".chatid\
@@ -149,6 +168,9 @@ async def keep_read(message):
\nUsage: Unmutes a muted chat.\
\n\n.mutechat\
\nUsage: Allows you to mute any chat.\
-\n\n.mention \
-\nUsage: Generate a permanent link to the user's profile with optional custom text."
+\n\n.link : (or) reply to someone's message with .link \
+\nUsage: Generate a permanent link to the user's profile with optional custom text.\
+\n\n.regexninja on/off\
+\nUsage: Globally enable/disables the regex ninja module.\
+\nRegex Ninja module helps to delete the regex bot's triggering messages."
})
diff --git a/userbot/modules/direct_links.py b/userbot/modules/direct_links.py
index 4e30a8fb1..af1255d91 100644
--- a/userbot/modules/direct_links.py
+++ b/userbot/modules/direct_links.py
@@ -15,11 +15,10 @@
from humanize import naturalsize
from userbot import CMD_HELP
-from userbot.events import register, errors_handler
+from userbot.events import register
@register(outgoing=True, pattern=r"^.direct(?: |$)([\s\S]*)")
-@errors_handler
async def direct_link_generator(request):
""" direct links generator """
await request.edit("`Processing...`")
diff --git a/userbot/modules/dogbin.py b/userbot/modules/dogbin.py
index 570c9162a..ac1469a13 100644
--- a/userbot/modules/dogbin.py
+++ b/userbot/modules/dogbin.py
@@ -9,13 +9,12 @@
import asyncio
import os
from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP, LOGS, TEMP_DOWNLOAD_DIRECTORY
-from userbot.events import register, errors_handler
+from userbot.events import register
DOGBIN_URL = "https://del.dog/"
@register(outgoing=True, pattern=r"^.paste(?: |$)([\s\S]*)")
-@errors_handler
async def paste(pstl):
""" For .paste command, pastes the text directly to dogbin. """
dogbin_final_url = ""
@@ -74,7 +73,6 @@ async def paste(pstl):
@register(outgoing=True, pattern="^.getpaste(?: |$)(.*)")
-@errors_handler
async def get_dogbin_content(dog_url):
""" For .getpaste command, fetches the content of a dogbin URL. """
textx = await dog_url.get_reply_message()
diff --git a/userbot/modules/evaluators.py b/userbot/modules/evaluators.py
index d90b5f0fc..455133f99 100644
--- a/userbot/modules/evaluators.py
+++ b/userbot/modules/evaluators.py
@@ -10,11 +10,10 @@
from os import remove
from sys import executable
from userbot import CMD_HELP, BOTLOG, BOTLOG_CHATID
-from userbot.events import register, errors_handler
+from userbot.events import register
@register(outgoing=True, pattern="^.eval(?: |$)(.*)")
-@errors_handler
async def evaluate(query):
""" For .eval command, evaluates the given Python expression. """
if query.is_channel and not query.is_group:
@@ -69,7 +68,6 @@ async def evaluate(query):
@register(outgoing=True, pattern=r"^.exec(?: |$)([\s\S]*)")
-@errors_handler
async def run(run_q):
""" For .exec command, which executes the dynamically created program """
code = run_q.pattern_match.group(1)
@@ -135,7 +133,6 @@ async def run(run_q):
@register(outgoing=True, pattern="^.term(?: |$)(.*)")
-@errors_handler
async def terminal_runner(term):
""" For .term command, runs bash commands and scripts on your server. """
curruser = getuser()
diff --git a/userbot/modules/filter.py b/userbot/modules/filter.py
index 2a10b0982..0c36c60ca 100644
--- a/userbot/modules/filter.py
+++ b/userbot/modules/filter.py
@@ -8,11 +8,10 @@
from asyncio import sleep
from re import fullmatch, IGNORECASE, escape
from userbot import BOTLOG, BOTLOG_CHATID, CMD_HELP
-from userbot.events import register, errors_handler
+from userbot.events import register
-@register(incoming=True, disable_edited=True)
-@errors_handler
+@register(incoming=True, disable_edited=True, disable_errors=True)
async def filter_incoming_handler(handler):
""" Checks if the incoming message contains handler of a filter """
try:
@@ -28,16 +27,17 @@ async def filter_incoming_handler(handler):
return
for trigger in filters:
pro = fullmatch(trigger.keyword, name, flags=IGNORECASE)
- if pro:
+ if pro and trigger.f_mesg_id:
msg_o = await handler.client.get_messages(
entity=BOTLOG_CHATID, ids=int(trigger.f_mesg_id))
await handler.reply(msg_o.message, file=msg_o.media)
+ elif pro and trigger.reply:
+ await handler.reply(trigger.reply)
except AttributeError:
pass
-@register(outgoing=True, pattern="^.filter (.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.filter (\w*)")
async def add_new_filter(new_handler):
""" For .filter command, allows adding new filters in a chat """
try:
@@ -46,35 +46,39 @@ async def add_new_filter(new_handler):
await new_handler.edit("`Running on Non-SQL mode!`")
return
keyword = new_handler.pattern_match.group(1)
+ string = new_handler.text.partition(keyword)[2]
msg = await new_handler.get_reply_message()
- if not msg:
- await new_handler.edit(
- "`I need something to save as reply to the filter.`")
- elif BOTLOG_CHATID:
- await new_handler.client.send_message(
- BOTLOG_CHATID, f"#FILTER\
- \nCHAT: {new_handler.chat.title}\
- \nTRIGGER: {keyword}\
- \nThe following message is saved as the filter's reply data for the chat, please do NOT delete it !!"
- )
- msg_o = await new_handler.client.forward_messages(
- entity=BOTLOG_CHATID,
- messages=msg,
- from_peer=new_handler.chat_id,
- silent=True)
- else:
- await new_handler.edit(
- "`This feature requires the BOTLOG_CHATID to be set.`")
- return
+ msg_id = None
+ if msg and msg.media and not string:
+ if BOTLOG_CHATID:
+ await new_handler.client.send_message(
+ BOTLOG_CHATID, f"#FILTER\
+ \nCHAT ID: {new_handler.chat_id}\
+ \nTRIGGER: {keyword}\
+ \n\nThe following message is saved as the filter's reply data for the chat, please do NOT delete it !!"
+ )
+ msg_o = await new_handler.client.forward_messages(
+ entity=BOTLOG_CHATID,
+ messages=msg,
+ from_peer=new_handler.chat_id,
+ silent=True)
+ msg_id = msg_o.id
+ else:
+ await new_handler.edit(
+ "`Saving media as reply to the filter requires the BOTLOG_CHATID to be set.`"
+ )
+ return
+ elif new_handler.reply_to_msg_id and not string:
+ rep_msg = await new_handler.get_reply_message()
+ string = rep_msg.text
success = "`Filter` **{}** `{} successfully`"
- if add_filter(str(new_handler.chat_id), keyword, msg_o.id) is True:
+ if add_filter(str(new_handler.chat_id), keyword, string, msg_id) is True:
await new_handler.edit(success.format(keyword, 'added'))
else:
await new_handler.edit(success.format(keyword, 'updated'))
-@register(outgoing=True, pattern="^.stop (.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.stop (\w*)")
async def remove_a_filter(r_handler):
""" For .stop command, allows you to remove a filter from a chat. """
try:
@@ -91,7 +95,6 @@ async def remove_a_filter(r_handler):
@register(outgoing=True, pattern="^.rmbotfilters (.*)")
-@errors_handler
async def kick_marie_filter(event):
""" For .rmfilters command, allows you to kick all \
Marie(or her clones) filters from a chat. """
@@ -119,7 +122,6 @@ async def kick_marie_filter(event):
@register(outgoing=True, pattern="^.filters$")
-@errors_handler
async def filters_active(event):
""" For .filters command, lists all of the active filters in a chat. """
try:
diff --git a/userbot/modules/gdrive.py b/userbot/modules/gdrive.py
index 96d1c62ab..51015b93f 100644
--- a/userbot/modules/gdrive.py
+++ b/userbot/modules/gdrive.py
@@ -1,8 +1,7 @@
-# Special thanks to @spechide & @Zero_cool7870 & @Prakaska :)
-# The entire code given below is verbatim copied from
-# https://github.com/cyberboysumanjay/Gdrivedownloader/blob/master/gdrive_upload.py
-# there might be some changes made to suit the needs for this repository
-# Licensed under MIT License
+# Copyright (C) 2019 The Raphielscape Company LLC.
+#
+# Licensed under the Raphielscape Public License, Version 1.c (the "License");
+# you may not use this file except in compliance with the License.
import asyncio
import math
@@ -19,7 +18,7 @@
from userbot import (G_DRIVE_CLIENT_ID, G_DRIVE_CLIENT_SECRET,
G_DRIVE_AUTH_TOKEN_DATA, GDRIVE_FOLDER_ID, BOTLOG_CHATID,
TEMP_DOWNLOAD_DIRECTORY, CMD_HELP, LOGS)
-from userbot.events import register, errors_handler
+from userbot.events import register
from mimetypes import guess_type
import httplib2
import subprocess
@@ -41,7 +40,6 @@
@register(pattern=r"^.gdrive(?: |$)(.*)", outgoing=True)
-@errors_handler
async def gdrive_upload_function(dryb):
""" For .gdrive command, upload files to google drive. """
await dryb.edit("Processing ...")
@@ -76,8 +74,9 @@ async def gdrive_upload_function(dryb):
speed = downloader.get_speed()
elapsed_time = round(diff) * 1000
progress_str = "[{0}{1}] {2}%".format(
- ''.join(["▰" for i in range(math.floor(percentage / 5))]),
- ''.join(["▱" for i in range(20 - math.floor(percentage / 5))]),
+ ''.join(["▰" for i in range(math.floor(percentage / 10))]),
+ ''.join(["▱"
+ for i in range(10 - math.floor(percentage / 10))]),
round(percentage, 2))
estimated_total_time = downloader.get_eta(human=True)
try:
@@ -145,7 +144,8 @@ async def gdrive_upload_function(dryb):
# Sometimes API fails to retrieve starting URI, we wrap it.
try:
g_drive_link = await upload_file(http, required_file_name,
- file_name, mime_type, dryb)
+ file_name, mime_type, dryb,
+ parent_id)
await dryb.edit(
f"File:`{required_file_name}`\nwas Successfully Uploaded to [Google Drive]({g_drive_link})!"
)
@@ -155,13 +155,9 @@ async def gdrive_upload_function(dryb):
@register(pattern=r"^.ggd(?: |$)(.*)", outgoing=True)
-@errors_handler
async def upload_dir_to_gdrive(event):
await event.edit("Processing ...")
if CLIENT_ID is None or CLIENT_SECRET is None:
- await event.edit(
- "This module requires credentials from https://da.gd/so63O. Aborting!"
- )
return
input_str = event.pattern_match.group(1)
if os.path.isdir(input_str):
@@ -186,13 +182,9 @@ async def upload_dir_to_gdrive(event):
@register(pattern=r"^.list(?: |$)(.*)", outgoing=True)
-@errors_handler
async def gdrive_search_list(event):
await event.edit("Processing ...")
if CLIENT_ID is None or CLIENT_SECRET is None:
- await event.edit(
- "This module requires credentials from https://da.gd/so63O. Aborting!"
- )
return
input_str = event.pattern_match.group(1).strip()
# TODO: remove redundant code
@@ -214,7 +206,6 @@ async def gdrive_search_list(event):
pattern=
r"^.gsetf https?://drive\.google\.com/drive/u/\d/folders/([-\w]{25,})",
outgoing=True)
-@errors_handler
async def download(set):
"""For .gsetf command, allows you to set path"""
await set.edit("Processing ...")
@@ -232,7 +223,6 @@ async def download(set):
@register(pattern="^.gsetclear$", outgoing=True)
-@errors_handler
async def download(gclr):
"""For .gsetclear command, allows you clear ur curnt custom path"""
await gclr.reply("Processing ...")
@@ -241,7 +231,6 @@ async def download(gclr):
@register(pattern="^.gfolder$", outgoing=True)
-@errors_handler
async def show_current_gdrove_folder(event):
if parent_id:
folder_link = f"https://drive.google.com/drive/folders/" + parent_id
@@ -295,7 +284,7 @@ def authorize(token_file, storage):
return http
-async def upload_file(http, file_path, file_name, mime_type, event):
+async def upload_file(http, file_path, file_name, mime_type, event, parent_id):
# Create Google Drive service instance
drive_service = build("drive", "v2", http=http, cache_discovery=False)
# File body description
@@ -324,9 +313,10 @@ async def upload_file(http, file_path, file_name, mime_type, event):
await asyncio.sleep(1)
if status:
percentage = int(status.progress() * 100)
- progress_str = "[{0}{1}] {2}%\n".format(
- "".join(["▰" for i in range(math.floor(percentage / 5))]),
- "".join(["▱" for i in range(20 - math.floor(percentage / 5))]),
+ progress_str = "[{0}{1}] {2}%".format(
+ "".join(["▰" for i in range(math.floor(percentage / 10))]),
+ "".join(["▱"
+ for i in range(10 - math.floor(percentage / 10))]),
round(percentage, 2))
current_message = f"Uploading to Google Drive\nFile Name: {file_name}\n{progress_str}"
if display_message != current_message:
@@ -385,7 +375,8 @@ async def DoTeskWithDir(http, input_directory, event, parent_id):
file_name, mime_type = file_ops(current_file_name)
# current_file_name will have the full path
g_drive_link = await upload_file(http, current_file_name,
- file_name, mime_type, event)
+ file_name, mime_type, event,
+ parent_id)
r_p_id = parent_id
# TODO: there is a #bug here :(
return r_p_id
@@ -454,11 +445,11 @@ async def gdrive_search(http, search_query):
".gdrive \
\nUsage: Uploads the file in reply , URL or file path in server to your Google Drive.\
\n\n.gsetf \
- \nUsage:Sets the folder to upload new files to.\
+ \nUsage: Sets the folder to upload new files to.\
\n\n.gsetclear\
- \nUsage:Reverts to default upload destination.\
+ \nUsage: Reverts to default upload destination.\
\n\n.gfolder\
- \nUsage:Shows your current upload destination/folder.\
+ \nUsage: Shows your current upload destination/folder.\
\n\n.list \
\nUsage: Looks for files and folders in your Google Drive.\
\n\n.ggd \
diff --git a/userbot/modules/github.py b/userbot/modules/github.py
deleted file mode 100644
index ce739d0d5..000000000
--- a/userbot/modules/github.py
+++ /dev/null
@@ -1,52 +0,0 @@
-import aiohttp
-from userbot.events import register, errors_handler
-from userbot import CMD_HELP
-
-
-@register(pattern=r".git (.*)", outgoing=True)
-@errors_handler
-async def github(event):
- URL = f"https://api.github.com/users/{event.pattern_match.group(1)}"
- chat = await event.get_chat()
- async with aiohttp.ClientSession() as session:
- async with session.get(URL) as request:
- if request.status == 404:
- await event.reply("`" + event.pattern_match.group(1) +
- " not found`")
- return
-
- result = await request.json()
-
- url = result.get("html_url", None)
- name = result.get("name", None)
- company = result.get("company", None)
- bio = result.get("bio", None)
- created_at = result.get("created_at", "Not Found")
-
- REPLY = f"GitHub Info for `{event.pattern_match.group(1)}`\
- \nUsername: `{name}`\
- \nBio: `{bio}`\
- \nURL: {url}\
- \nCompany: `{company}`\
- \nCreated at: `{created_at}`"
-
- if not result.get("repos_url", None):
- await event.edit(REPLY)
- return
- async with session.get(result.get("repos_url", None)) as request:
- result = request.json
- if request.status == 404:
- await event.edit(REPLY)
- return
-
- result = await request.json()
-
- REPLY += "\nRepos:\n"
-
- for nr in range(len(result)):
- REPLY += f"[{result[nr].get('name', None)}]({result[nr].get('html_url', None)})\n"
-
- await event.edit(REPLY)
-
-
-CMD_HELP.update({"git": "Like .whois but for GitHub usernames."})
diff --git a/userbot/modules/hash.py b/userbot/modules/hash.py
index ac3e724cf..eb950cbe3 100644
--- a/userbot/modules/hash.py
+++ b/userbot/modules/hash.py
@@ -9,11 +9,10 @@
from subprocess import run as runapp
import pybase64
from userbot import CMD_HELP
-from userbot.events import register, errors_handler
+from userbot.events import register
@register(outgoing=True, pattern="^.hash (.*)")
-@errors_handler
async def gethash(hash_q):
""" For .hash command, find the md5, sha1, sha256, sha512 of the string. """
hashtxt_ = hash_q.pattern_match.group(1)
@@ -46,7 +45,6 @@ async def gethash(hash_q):
@register(outgoing=True, pattern="^.base64 (en|de) (.*)")
-@errors_handler
async def endecrypt(query):
""" For .base64 command, find the base64 encoding of the given string. """
if query.pattern_match.group(1) == "en":
diff --git a/userbot/modules/help.py b/userbot/modules/help.py
index 3701e4506..63ad6b276 100644
--- a/userbot/modules/help.py
+++ b/userbot/modules/help.py
@@ -6,11 +6,10 @@
""" Userbot help command """
from userbot import CMD_HELP
-from userbot.events import register, errors_handler
+from userbot.events import register
@register(outgoing=True, pattern="^.help(?: |$)(.*)")
-@errors_handler
async def help(event):
""" For .help command,"""
args = event.pattern_match.group(1).lower()
diff --git a/userbot/modules/lastfm.py b/userbot/modules/lastfm.py
index 685e52244..65b0a8833 100644
--- a/userbot/modules/lastfm.py
+++ b/userbot/modules/lastfm.py
@@ -18,7 +18,7 @@
from telethon.errors.rpcerrorlist import FloodWaitError
from userbot import CMD_HELP, BOTLOG, BOTLOG_CHATID, DEFAULT_BIO, BIO_PREFIX, lastfm, LASTFM_USERNAME, bot
-from userbot.events import register, errors_handler
+from userbot.events import register
# =================== CONSTANT ===================
LFM_BIO_ENABLED = "```last.fm current music to bio is now enabled.```"
@@ -46,7 +46,6 @@
@register(outgoing=True, pattern="^.lastfm$")
-@errors_handler
async def last_fm(lastFM):
""" For .lastfm command, fetch scrobble data from last.fm. """
await lastFM.edit("Processing...")
@@ -179,7 +178,6 @@ async def get_curr_track(lfmbio):
@register(outgoing=True, pattern=r"^.lastbio (on|off)")
-@errors_handler
async def lastbio(lfmbio):
arg = lfmbio.pattern_match.group(1).lower()
global LASTFMCHECK
@@ -204,7 +202,6 @@ async def lastbio(lfmbio):
@register(outgoing=True, pattern=r"^.lastlog (on|off)")
-@errors_handler
async def lastlog(lstlog):
arg = lstlog.pattern_match.group(1).lower()
global LastLog
diff --git a/userbot/modules/locks.py b/userbot/modules/locks.py
index a89a71522..db3f57465 100644
--- a/userbot/modules/locks.py
+++ b/userbot/modules/locks.py
@@ -1,12 +1,16 @@
+# Copyright (C) 2019 The Raphielscape Company LLC.
+#
+# Licensed under the Raphielscape Public License, Version 1.c (the "License");
+# you may not use this file except in compliance with the License.
+
from telethon.tl.functions.messages import EditChatDefaultBannedRightsRequest
from telethon.tl.types import ChatBannedRights
from userbot import CMD_HELP
-from userbot.events import register, errors_handler
+from userbot.events import register
@register(outgoing=True, pattern=r"^.lock ?(.*)")
-@errors_handler
async def locks(event):
input_str = event.pattern_match.group(1).lower()
peer_id = event.chat_id
@@ -95,7 +99,6 @@ async def locks(event):
@register(outgoing=True, pattern=r"^.unlock ?(.*)")
-@errors_handler
async def rem_locks(event):
input_str = event.pattern_match.group(1).lower()
peer_id = event.chat_id
diff --git a/userbot/modules/memes.py b/userbot/modules/memes.py
index 82c775426..a727aa63c 100644
--- a/userbot/modules/memes.py
+++ b/userbot/modules/memes.py
@@ -2,26 +2,21 @@
#
# Licensed under the Raphielscape Public License, Version 1.c (the "License");
# you may not use this file except in compliance with the License.
-#
-#
""" Userbot module for having some fun with people. """
-import asyncio
-import random
-import re
+from asyncio import sleep
+from random import choice, getrandbits, randint
+from re import sub
import time
from collections import deque
import requests
-from telethon.tl.functions.users import GetFullUserRequest
-from telethon.tl.types import MessageEntityMentionName
-
from cowpy import cow
from userbot import CMD_HELP
-from userbot.events import register, errors_handler
+from userbot.events import register
from userbot.modules.admin import get_user_from_event
# ================= CONSTANT =================
@@ -614,7 +609,6 @@
@register(outgoing=True, pattern=r"^.(\w+)say (.*)")
-@errors_handler
async def univsaye(cowmsg):
""" For .cowsay module, userbot wrapper for cow which says things. """
arg = cowmsg.pattern_match.group(1).lower()
@@ -630,8 +624,7 @@ async def univsaye(cowmsg):
await cowmsg.edit(f"`{cheese.milk(text).replace('`', '´')}`")
-@register(outgoing=True, pattern="^:/$")
-@errors_handler
+@register(outgoing=True, pattern="^:/$", ignore_unsafe=True)
async def kek(keks):
""" Check yourself ;)"""
uio = ["/", "\\"]
@@ -641,9 +634,8 @@ async def kek(keks):
@register(outgoing=True, pattern=r"^.coinflip (.*)")
-@errors_handler
async def coin(event):
- r = random.choice(["heads", "tails"])
+ r = choice(["heads", "tails"])
input_str = event.pattern_match.group(1)
if input_str:
input_str = input_str.lower()
@@ -670,19 +662,14 @@ async def coin(event):
@register(pattern="^.slap(?: |$)(.*)", outgoing=True)
-@errors_handler
async def who(event):
""" slaps a user, or get slapped if not a reply. """
replied_user = await get_user_from_event(event)
if replied_user:
replied_user = replied_user[0]
else:
- await event.edit("`I can't slap nothing !!`")
+ return
caption = await slap(replied_user, event)
- message_id_to_reply = event.message.reply_to_msg_id
-
- if not message_id_to_reply:
- message_id_to_reply = None
try:
await event.edit(caption)
@@ -704,11 +691,11 @@ async def slap(replied_user, event):
else:
slapped = f"[{first_name}](tg://user?id={user_id})"
- temp = random.choice(SLAP_TEMPLATES)
- item = random.choice(ITEMS)
- hit = random.choice(HIT)
- throw = random.choice(THROW)
- where = random.choice(WHERE)
+ temp = choice(SLAP_TEMPLATES)
+ item = choice(ITEMS)
+ hit = choice(HIT)
+ throw = choice(THROW)
+ where = choice(WHERE)
caption = "..." + temp.format(
victim=slapped, item=item, hits=hit, throws=throw, where=where)
@@ -716,8 +703,7 @@ async def slap(replied_user, event):
return caption
-@register(outgoing=True, pattern="^-_-$")
-@errors_handler
+@register(outgoing=True, pattern="^-_-$", ignore_unsafe=True)
async def lol(lel):
""" Ok... """
okay = "-_-"
@@ -726,34 +712,22 @@ async def lol(lel):
await lel.edit(okay)
-@register(outgoing=True, pattern="^.decide(?: |$)(.*)")
-@errors_handler
+@register(outgoing=True, pattern="^.(yes|no|maybe|decide)$")
async def decide(event):
decision = event.pattern_match.group(1).lower()
- message_id = None
- if event.reply_to_msg_id:
- message_id = event.reply_to_msg_id
- if not decision:
- r = requests.get("https://yesno.wtf/api").json()
+ message_id = event.reply_to_msg_id if event.reply_to_msg_id else None
+ if decision != "decide":
+ r = requests.get(f"https://yesno.wtf/api?force={decision}").json()
else:
- try:
- options = ["yes", "no", "maybe"]
- if decision not in options:
- await event.edit("`Available decisions:` *yes*, *no*, *maybe*")
- return
- r = requests.get(f"https://yesno.wtf/api?force={decision}").json()
- except Excepption as err:
- await event.edit(f"`Error:` {str(err)}")
- return
+ r = requests.get(f"https://yesno.wtf/api").json()
+ await event.delete()
await event.client.send_message(event.chat_id,
str(r["answer"]).upper(),
reply_to=message_id,
file=r["image"])
- await event.delete()
-@register(outgoing=True, pattern="^;_;$")
-@errors_handler
+@register(outgoing=True, pattern="^;_;$", ignore_unsafe=True)
async def fun(e):
t = ";_;"
for j in range(10):
@@ -762,28 +736,24 @@ async def fun(e):
@register(outgoing=True, pattern="^.fp$")
-@errors_handler
async def facepalm(e):
""" Facepalm 🤦♂ """
await e.edit("🤦♂")
@register(outgoing=True, pattern="^.cry$")
-@errors_handler
async def cry(e):
""" y u du dis, i cry everytime !! """
- await e.edit(random.choice(CRI))
+ await e.edit(choice(CRI))
@register(outgoing=True, pattern="^.insult$")
-@errors_handler
async def insult(e):
""" I make you cry !! """
- await e.edit(random.choice(INSULT_STRINGS))
+ await e.edit(choice(INSULT_STRINGS))
@register(outgoing=True, pattern="^.cp(?: |$)(.*)")
-@errors_handler
async def copypasta(cp_e):
""" Copypasta the famous meme """
textx = await cp_e.get_reply_message()
@@ -797,28 +767,27 @@ async def copypasta(cp_e):
await cp_e.edit("`😂🅱️IvE👐sOME👅text👅for✌️Me👌tO👐MAkE👀iT💞funNy!💦`")
return
- reply_text = random.choice(EMOJIS)
+ reply_text = choice(EMOJIS)
# choose a random character in the message to be substituted with 🅱️
- b_char = random.choice(message).lower()
+ b_char = choice(message).lower()
for owo in message:
if owo == " ":
- reply_text += random.choice(EMOJIS)
+ reply_text += choice(EMOJIS)
elif owo in EMOJIS:
reply_text += owo
- reply_text += random.choice(EMOJIS)
+ reply_text += choice(EMOJIS)
elif owo.lower() == b_char:
reply_text += "🅱️"
else:
- if bool(random.getrandbits(1)):
+ if bool(getrandbits(1)):
reply_text += owo.upper()
else:
reply_text += owo.lower()
- reply_text += random.choice(EMOJIS)
+ reply_text += choice(EMOJIS)
await cp_e.edit(reply_text)
@register(outgoing=True, pattern="^.vapor(?: |$)(.*)")
-@errors_handler
async def vapor(vpr):
""" Vaporize everything! """
reply_text = list()
@@ -844,7 +813,6 @@ async def vapor(vpr):
@register(outgoing=True, pattern="^.str(?: |$)(.*)")
-@errors_handler
async def stretch(stret):
""" Stretch it."""
textx = await stret.get_reply_message()
@@ -858,14 +826,13 @@ async def stretch(stret):
await stret.edit("`GiiiiiiiB sooooooomeeeeeee teeeeeeext!`")
return
- count = random.randint(3, 10)
- reply_text = re.sub(r"([aeiouAEIOUaeiouAEIOUаеиоуюяыэё])", (r"\1" * count),
- message)
+ count = randint(3, 10)
+ reply_text = sub(r"([aeiouAEIOUaeiouAEIOUаеиоуюяыэё])", (r"\1" * count),
+ message)
await stret.edit(reply_text)
@register(outgoing=True, pattern="^.zal(?: |$)(.*)")
-@errors_handler
async def zal(zgfy):
""" Invoke the feeling of chaos. """
reply_text = list()
@@ -887,17 +854,17 @@ async def zal(zgfy):
continue
for _ in range(0, 3):
- randint = random.randint(0, 2)
+ randint = randint(0, 2)
if randint == 0:
charac = charac.strip() + \
- random.choice(ZALG_LIST[0]).strip()
+ choice(ZALG_LIST[0]).strip()
elif randint == 1:
charac = charac.strip() + \
- random.choice(ZALG_LIST[1]).strip()
+ choice(ZALG_LIST[1]).strip()
else:
charac = charac.strip() + \
- random.choice(ZALG_LIST[2]).strip()
+ choice(ZALG_LIST[2]).strip()
reply_text.append(charac)
@@ -905,14 +872,12 @@ async def zal(zgfy):
@register(outgoing=True, pattern="^.hi$")
-@errors_handler
async def hoi(hello):
""" Greet everyone! """
- await hello.edit(random.choice(HELLOSTR))
+ await hello.edit(choice(HELLOSTR))
@register(outgoing=True, pattern="^.owo(?: |$)(.*)")
-@errors_handler
async def faces(owo):
""" UwU """
textx = await owo.get_reply_message()
@@ -925,53 +890,47 @@ async def faces(owo):
await owo.edit("` UwU no text given! `")
return
- reply_text = re.sub(r"(r|l)", "w", message)
- reply_text = re.sub(r"(R|L)", "W", reply_text)
- reply_text = re.sub(r"n([aeiou])", r"ny\1", reply_text)
- reply_text = re.sub(r"N([aeiouAEIOU])", r"Ny\1", reply_text)
- reply_text = re.sub(r"\!+", " " + random.choice(UWUS), reply_text)
+ reply_text = sub(r"(r|l)", "w", message)
+ reply_text = sub(r"(R|L)", "W", reply_text)
+ reply_text = sub(r"n([aeiou])", r"ny\1", reply_text)
+ reply_text = sub(r"N([aeiouAEIOU])", r"Ny\1", reply_text)
+ reply_text = sub(r"\!+", " " + choice(UWUS), reply_text)
reply_text = reply_text.replace("ove", "uv")
- reply_text += " " + random.choice(UWUS)
+ reply_text += " " + choice(UWUS)
await owo.edit(reply_text)
@register(outgoing=True, pattern="^.react$")
-@errors_handler
async def react_meme(react):
""" Make your userbot react to everything. """
- await react.edit(random.choice(FACEREACTS))
+ await react.edit(choice(FACEREACTS))
@register(outgoing=True, pattern="^.shg$")
-@errors_handler
async def shrugger(shg):
r""" ¯\_(ツ)_/¯ """
- await shg.edit(random.choice(SHGS))
+ await shg.edit(choice(SHGS))
@register(outgoing=True, pattern="^.chase$")
-@errors_handler
async def police(chase):
""" Run boi run, i'm gonna catch you !! """
- await chase.edit(random.choice(CHASE_STR))
+ await chase.edit(choice(CHASE_STR))
@register(outgoing=True, pattern="^.run$")
-@errors_handler
async def runner_lol(run):
""" Run, run, RUNNN! """
- await run.edit(random.choice(RUNS_STR))
+ await run.edit(choice(RUNS_STR))
@register(outgoing=True, pattern="^.metoo$")
-@errors_handler
async def metoo(hahayes):
""" Haha yes """
- await hahayes.edit(random.choice(METOOSTR))
+ await hahayes.edit(choice(METOOSTR))
-@register(outgoing=True, pattern="^.oof$")
-@errors_handler
+@register(outgoing=True, pattern="^Oof$")
async def Oof(e):
t = "Oof"
for j in range(15):
@@ -980,18 +939,16 @@ async def Oof(e):
@register(outgoing=True, pattern="^.10iq$")
-@errors_handler
async def iqless(e):
await e.edit("♿")
@register(outgoing=True, pattern="^.moon$")
-@errors_handler
async def moon(event):
deq = deque(list("🌗🌘🌑🌒🌓🌔🌕🌖"))
try:
for x in range(32):
- await asyncio.sleep(0.1)
+ await sleep(0.1)
await event.edit("".join(deq))
deq.rotate(1)
except BaseException:
@@ -999,12 +956,11 @@ async def moon(event):
@register(outgoing=True, pattern="^.clock$")
-@errors_handler
async def clock(event):
deq = deque(list("🕙🕘🕗🕖🕕🕔🕓🕒🕑🕐🕛"))
try:
for x in range(32):
- await asyncio.sleep(0.1)
+ await sleep(0.1)
await event.edit("".join(deq))
deq.rotate(1)
except BaseException:
@@ -1012,7 +968,6 @@ async def clock(event):
@register(outgoing=True, pattern="^.mock(?: |$)(.*)")
-@errors_handler
async def spongemocktext(mock):
""" Do it and find the real fun. """
reply_text = list()
@@ -1027,7 +982,7 @@ async def spongemocktext(mock):
return
for charac in message:
- if charac.isalpha() and random.randint(0, 1):
+ if charac.isalpha() and randint(0, 1):
to_app = charac.upper() if charac.islower() else charac.lower()
reply_text.append(to_app)
else:
@@ -1037,7 +992,6 @@ async def spongemocktext(mock):
@register(outgoing=True, pattern="^.clap(?: |$)(.*)")
-@errors_handler
async def claptext(memereview):
""" Praise people! """
textx = await memereview.get_reply_message()
@@ -1056,18 +1010,15 @@ async def claptext(memereview):
@register(outgoing=True, pattern="^.bt$")
-@errors_handler
async def bluetext(bt_e):
""" Believe me, you will find this useful. """
if await bt_e.get_reply_message() and bt_e.is_group:
await bt_e.edit(
"/BLUETEXT /MUST /CLICK.\n"
- "/ARE /YOU /A /STUPID /ANIMAL /WHICH /IS /ATTRACTED /TO /COLOURS ?"
- )
+ "/ARE /YOU /A /STUPID /ANIMAL /WHICH /IS /ATTRACTED /TO /COLOURS?")
@register(outgoing=True, pattern=r"^.f (.*)")
-@errors_handler
async def payf(event):
paytext = event.pattern_match.group(1)
pay = "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}".format(
@@ -1078,7 +1029,6 @@ async def payf(event):
@register(outgoing=True, pattern="^.lfy (.*)")
-@errors_handler
async def let_me_google_that_for_you(lmgtfy_q):
textx = await lmgtfy_q.get_reply_message()
qry = lmgtfy_q.pattern_match.group(1)
@@ -1096,7 +1046,6 @@ async def let_me_google_that_for_you(lmgtfy_q):
@register(pattern=r".scam(?: |$)(.*)", outgoing=True)
-@errors_handler
async def scam(event):
""" Just a small command to fake chat actions for fun !! """
options = [
@@ -1106,14 +1055,14 @@ async def scam(event):
input_str = event.pattern_match.group(1)
args = input_str.split()
if len(args) is 0: # Let bot decide action and time
- scam_action = random.choice(options)
- scam_time = random.randint(30, 60)
+ scam_action = choice(options)
+ scam_time = randint(30, 60)
elif len(args) is 1: # User decides time/action, bot decides the other.
try:
scam_action = str(args[0]).lower()
- scam_time = random.randint(30, 60)
+ scam_time = randint(30, 60)
except ValueError:
- scam_action = random.choice(options)
+ scam_action = choice(options)
scam_time = int(args[0])
elif len(args) is 2: # User decides both action and time
scam_action = str(args[0]).lower()
@@ -1125,13 +1074,12 @@ async def scam(event):
if (scam_time > 0):
await event.delete()
async with event.client.action(event.chat_id, scam_action):
- await asyncio.sleep(scam_time)
+ await sleep(scam_time)
except BaseException:
return
@register(pattern=r".type(?: |$)(.*)", outgoing=True)
-@errors_handler
async def typewriter(typew):
""" Just a small command to make your keyboard become a typewriter! """
textx = await typew.get_reply_message()
@@ -1147,14 +1095,14 @@ async def typewriter(typew):
typing_symbol = "|"
old_text = ""
await typew.edit(typing_symbol)
- await asyncio.sleep(sleep_time)
+ await sleep(sleep_time)
for character in message:
old_text = old_text + "" + character
typing_text = old_text + "" + typing_symbol
await typew.edit(typing_text)
- await asyncio.sleep(sleep_time)
+ await sleep(sleep_time)
await typew.edit(old_text)
- await asyncio.sleep(sleep_time)
+ await sleep(sleep_time)
CMD_HELP.update({
@@ -1217,7 +1165,7 @@ async def typewriter(typew):
\nUsage: Just a small command to make your keyboard become a typewriter!\
\n\n.lfy \
\nUsage: Let me Google that for you real quick !!\
-\n\n.decide [Optional: (yes, no, maybe)]\
+\n\n.decide [Alternates: (.yes, .no, .maybe)]\
\nUsage: Make a quick decision.\
\n\n.scam