wowee i did a thing

pull/1/head
Matt C 3 years ago
parent 9f94be1e35
commit 2878bbf45e

@ -1,5 +1,2 @@
# caveman
Discord bot (pycord) for monitoring repos and stuff
Based on Matt's Gamerbot2 from https://git.tar.black/matt/Gamerbot2
Bang rock together make package tracker bot

167
bot.py

@ -1,164 +1,15 @@
# Standard python imports
import os, string, unicodedata, sys, re, random, time, datetime, subprocess, json, traceback
import urllib.parse
import importlib
from os import listdir
from os.path import isfile, join
# Pycord
import discord
import discord,os
from discord.ext import commands
# Kind've discord related
from pretty_help import DefaultMenu, PrettyHelp
# Other pip packages
import asyncio
import requests
# My own classes n such
from global_config import configboi
from util_functions import *
if os.path.sep == "\\":
print("This bot is only supported on UNIX-like systems. Aborting.")
sys.exit(1)
intents = discord.Intents.default()
intents.members = True
# Start event handling and bot creation
bot = commands.Bot(
command_prefix=commands.when_mentioned_or(";"),
description="Ooga booga hit rocks together",
intents=intents,
)
helpmenu = DefaultMenu("◀️", "▶️", "")
bot.help_command = PrettyHelp(
no_category="Commands", navigation=helpmenu, color=discord.Colour.blurple()
)
# Sane default?
my_homedir = os.getenv("HOME", "/home/caveman")
# No default b/c we're fucked long before this if PATH is none
old_path = os.getenv("PATH")
new_path = old_path + ":" + my_homedir + "/.local/bin/"
os.environ["PATH"] = new_path
print("Our PATH is: " + os.getenv("PATH"))
# Startup event
@bot.event
async def on_ready():
syslog.log("Main-Important", "Bot has restarted at " + getstamp())
syslog.log("Main", f"\n{bot.user} has connected to Discord!\n")
if check("restarted.txt"):
channel = get("restarted.txt")
chan = bot.get_channel(int(channel))
if chan is not None:
await chan.send(
embed=infmsg("System", "Finished restarting at: `" + getstamp() + "`")
)
os.remove("restarted.txt")
ownerman = await bot.fetch_user(OWNER)
notifyowner = confmgr.getasbool("OWNER_DM_RESTART")
from task import Packages
cogs_dir = "cogs"
for extension in [
f.replace(".py", "") for f in listdir(cogs_dir) if isfile(join(cogs_dir, f))
]:
try:
bot.load_extension(cogs_dir + "." + extension)
syslog.log("Main", "Loaded " + extension)
# await ownerman.send(embed=infmsg("System","Loaded `" + extension + "`"))
except (Exception) as e:
await ownerman.send(
embed=errmsg(
"System", "Error from cog: " + extension + ": ```" + str(e) + "```"
)
)
syslog.log("Main", f"Failed to load extension {extension}.")
# traceback.print_exc()
bot = commands.Bot(";")
bot.add_cog(Packages(bot))
if notifyowner:
await ownerman.send(
embed=infmsg("System", "Started/restarted at: `" + getstamp() + "`")
)
@bot.event
async def on_message(message):
if message.author != bot.user:
mc = message.content
if "bot" in mc:
# we're being talked to
if "bad" in mc or "sucks" in mc:
await message.channel.send(":(")
await bot.process_commands(message)
@bot.event
async def on_command_error(ctx, error):
syslog.log("Main", "Error in command: " + str(error))
await ctx.send(embed=errmsg("Error", "```" + str(error) + "```"))
@bot.command()
async def removecog(ctx, name):
"""Un-load a cog that was loaded by default."""
if ctx.message.author.id == OWNER:
await ctx.send(embed=infmsg("Gotcha", "Ok, I'll try to disable `" + name + "`"))
try:
bot.remove_cog(name)
syslog.log("Main", "Disabled cog: " + name)
await ctx.send(embed=warnmsg("Done", "Disabled: `" + name + "`."))
except Exception as e:
await ctx.send(
embed=errmsg("Broke", "Something went wrong: `" + str(e) + "`.")
)
else:
await ctx.send(embed=errmsg("Oops", wrongperms("removecog")))
@bot.command()
async def getsyslog(ctx):
"""Get a copy of the system log"""
if ctx.message.author.id == OWNER:
log = syslog.getlog()
if len(log) > 1994:
text = paste(log)
await ctx.send(embed=infmsg("Output", text))
else:
text = "```" + log + "```"
await ctx.send("Here you go:")
await ctx.send(text)
else:
await ctx.send(embed=errmsg("Oops", wrongperms("getsyslog")))
if UNLOAD_COGS is not None:
# Remove any cogs as per config
for item in UNLOAD_COGS:
if item != "" and item != " ":
syslog.log("Main", "Trying to remove '" + item + "'")
try:
bot.remove_cog(item)
syslog.log("Main", "Removed '" + item + "'")
except:
syslog.log("Main", "Failed to remove '" + item + "'")
if check(".cavetoken"):
token = open(".cavetoken").read().strip()
if not os.path.exists(os.environ["HOME"] + "/.cavetoken"):
print("No token found")
exit()
else:
fail("No token found in .cavetoken")
bot.run(token)
token = open(os.environ["HOME"] + "/.cavetoken", "r").read()
bot.run(token)

@ -1,68 +0,0 @@
import discord
from discord.ext import commands
from util_functions import *
# Hopefully we'll never need logging here
class About(commands.Cog):
"""Stuff that the developer couldn't find a better category for"""
def __init__(self, bot):
self.bot = bot
@commands.command()
async def source(self, ctx):
"""Bot source code link"""
await ctx.send(
embed=infmsg(
"Source",
"My source code lives here: https://git.getcryst.al/crystal/caveman",
)
)
@commands.command()
async def report(self, ctx):
"""Report bot issues"""
await ctx.send(
embed=infmsg(
"Issues",
"You can file issues here: https://git.getcryst.al/crystal/caveman/issues",
)
)
@commands.command()
async def suggest(self, ctx):
"""Suggest bot feature(s)"""
await ctx.send(
embed=infmsg(
"Issues",
"You can file issues here: https://git.getcryst.al/crystal/caveman/issues",
)
)
@commands.command()
async def version(self, ctx):
"""Bot version"""
commit_msg = await run_command_shell(
"git --no-pager log --decorate=short --pretty=oneline -n1"
)
msg = ""
msg += "Latest Git commit: \n"
msg += "```" + commit_msg + "```"
await ctx.send(embed=infmsg("Bot Stats", msg))
@commands.command()
async def invite(self, ctx):
"""Add me to another server"""
await ctx.send(
embed=infmsg(
"Invite me :)",
"https://discord.com/api/oauth2/authorize?client_id=900841588996063282&permissions=8&scope=bot%20applications.commands",
)
)
def setup(bot):
bot.add_cog(About(bot))

@ -1,130 +0,0 @@
import discord
from discord.ext import commands
from util_functions import *
from global_config import configboi
# Hopefully we'll never need logging here
class Debug(commands.Cog):
"""Stuff that the developer couldn't find a better category for"""
def __init__(self, bot):
self.bot = bot
self.confmgr = configboi("config.txt", False)
@commands.command()
async def checkcog(self, ctx, *, n):
"""check if cog is a thing"""
try:
if ctx.bot.get_cog(n) is not None:
await ctx.send(
embed=infmsg("Debug Tools", "Bot was able to find `" + n + "`")
)
else:
await ctx.send(
embed=errmsg("Debug Tools", "Bot was not able to find `" + n + "`")
)
except Exception as e:
await ctx.send(
embed=errmsg(
"Debug Tools - ERROR",
"Had error `" + str(e) + "` while checking cog `" + n + "`",
)
)
@commands.command()
async def restart(self, ctx):
"""Restart the bot (Mod. only)"""
if ctx.message.author.id == OWNER:
await ctx.send(embed=infmsg("Sad", "Ok, restarting"))
if ctx.voice_client is not None:
await ctx.voice_client.disconnect()
await ctx.bot.logout()
syslog.log(
"Admin-Important",
"Bot is restarting because "
+ ctx.message.author.display_name
+ " requested we do so.",
)
save("restarted.txt", str(ctx.message.channel.id))
await login(os.environ["bottoken"], bot=True)
else:
await ctx.send(embed=errmsg("Oops", wrongperms("restart")))
@commands.command()
async def update(self, ctx):
"""Update bot from Git, and restart (Mod. only)"""
if ctx.message.author.id == OWNER:
await ctx.send(embed=infmsg("Updater", "Updating..."))
syslog.log(
"Admin-Important",
"Bot is updating & restarting because "
+ ctx.message.author.display_name
+ " requested we do so.",
)
# are these being upset?
pull_out = await run_command_shell("git pull -v")
commit_msg = await run_command_shell(
"git --no-pager log --decorate=short --pretty=oneline -n1"
)
msg = (
"Changes:"
+ "\n```"
+ pull_out
+ "```\nCommit message:\n"
+ "```"
+ commit_msg
+ "```"
)
await ctx.send(embed=infmsg("Updater", msg))
await run_command_shell("pip3 install --upgrade -r requirements.txt")
await ctx.send(embed=infmsg("Updater", "Restarting"))
if ctx.voice_client is not None:
await ctx.voice_client.disconnect()
await ctx.bot.logout()
save("restarted.txt", str(ctx.message.channel.id))
await login(os.environ["bottoken"], bot=True)
else:
await ctx.send(embed=errmsg("Oops", wrongperms("update")))
@commands.command()
async def chbranch(self, ctx, *, branch):
"""Switch bot's upstream to a given branch (Mod. only)"""
if ctx.message.author.id == OWNER:
await ctx.send(embed=infmsg("Updater", "Switching branch..."))
syslog.log(
"Admin-Important",
"Bot is switching branch to "
+ branch
+ " because "
+ ctx.message.author.display_name
+ " requested we do so.",
)
await run_command_shell("git checkout " + branch)
await ctx.send(embed=infmsg("Updater", "Done!"))
else:
await ctx.send(embed=errmsg("Oops", wrongperms("chbranch")))
@commands.command()
async def gitstatus(self, ctx):
"""Show the output of git status"""
commit_msg = await run_command_shell(
"git --no-pager log --decorate=short --pretty=oneline -n1"
)
await ctx.send(embed=infmsg("Git Status", "```" + commit_msg + "```"))
@commands.command()
async def purgesyslog(self, ctx):
"""Delete all existing syslogs (USE WITH CARE) (Owner only)"""
if ctx.message.author.id == OWNER:
purged = await run_command_shell("rm system_log* -v")
await ctx.send(embed=infmsg("Syslog Purger", "We purged:\n```" + purged + "```"))
else:
await ctx.send(embed=errmsg("Oops", wrongperms("purgesyslog")))
def setup(bot):
bot.add_cog(Debug(bot))

@ -1,23 +0,0 @@
import discord
from discord.ext import commands
from util_functions import *
# Hopefully we'll never need logging here
class Random(commands.Cog):
"""Stuff that the developer couldn't find a better category for"""
def __init__(self, bot):
self.bot = bot
@commands.command()
async def ping(self, ctx):
"""pong."""
await ctx.send(
"pong. :upside_down: :gun:", file=discord.File("images/pong.jpg")
)
def setup(bot):
bot.add_cog(Random(bot))

@ -1,110 +0,0 @@
import sys, datetime, os
import discord
from discord.ext import commands, tasks
import feedparser,requests
from global_config import configboi
from util_functions import *
sc = configboi("config.txt", False)
REFRESH_TIME = sc.getasint("REFRESH_TIME")
class RSS(commands.Cog):
"""This cog handles RSS stuff"""
def __init__(self, bot):
self.bot = bot
self.confmgr = configboi("config.txt", False)
self.package_names = self.confmgr.getaslist("WATCHED_PACKAGES")
temp = self.confmgr.getaslist("FEED_URLS")
self.gitea_urls = self.confmgr.getaslist("GITEA_URLS")
self.package_channel = self.confmgr.getasint("PACKAGE_CHANNEL")
self.feed_urls = []
for feed in temp:
self.feed_urls.append("https://" + feed)
self.chan = self.bot.get_channel(self.package_channel)
if self.chan is None:
syslog.log("RSS", "Package task failed because we couldn't find the target channel.")
sys.exit(1)
self.root = "package-cache"
ensure(self.root)
self.package_task.start()
def cog_unload(self):
self.package_task.cancel()
@commands.Cog.listener()
async def on_ready(self):
syslog.log("RSS", "Running initial package check")
await self.check_packages()
@tasks.loop(seconds=REFRESH_TIME)
async def package_task(self):
await self.check_packages()
@package_task.before_loop
async def before_status_task(self):
syslog.log(
"RSS", "Waiting for bot to be ready before starting package task"
)
await self.bot.wait_until_ready()
syslog.log("RSS", "Bot is ready. Enabling package task")
async def sendwarn(self, msg):
await self.chan.send(embed=warnmsg("RSS",msg))
async def senderr(self, msg):
await self.chan.send(embed=errmsg("RSS",msg))
async def send(self, msg):
await self.chan.send(embed=infmsg("RSS",msg))
def dolog(self, msg):
syslog.log("RSS", msg)
async def check_packages(self):
try:
for feed in self.feed_urls:
self.dolog("Checking: " + feed)
previous = ""
if check(self.root + "/" + feed.replace("/","-")):
self.dolog("Found previous cached data")
previous = open(self.root + "/" + feed.replace("/","-")).read().strip()
else:
self.dolog("No previous data")
new = requests.get(feed).text
if new != previous:
self.dolog("New data is different")
if check(self.root + "/" + feed.replace("/","-")):
os.remove(self.root + "/" + feed.replace("/","-"))
with open(self.root + "/" + feed.replace("/","-"), "w") as f:
f.write(new)
self.dolog("Updated cache")
d = feedparser.parse(new)
for item in d.entries:
pkgn = str(item['title'])
if " " in pkgn:
pkgn = pkgn.split(" ")[0]
for tgt in self.package_names:
if tgt in pkgn:
await self.send("Package change: `" + str(item['title']) + "`")
break
except Exception as e:
syslog.log("RSS ERROR", str(e))
def setup(bot):
bot.add_cog(RSS(bot))

@ -1,91 +0,0 @@
import sys, datetime
import discord
from discord.ext import commands, tasks
from global_config import configboi
from util_functions import *
class Status(commands.Cog):
"""This cog keeps the bot status in sync"""
def __init__(self, bot):
self.bot = bot
self.confmgr = configboi("config.txt", False)
self.status_task.start()
self.uptime_logger.start()
self.upt = 0
def cog_unload(self):
self.status_task.cancel()
self.uptime_logger.cancel()
async def setDefaultStatus(self):
ac_type = None
if self.confmgr.get("DEFAULT_STATUS_TYPE") == "watching":
ac_type = discord.ActivityType.watching
elif self.confmgr.get("DEFAULT_STATUS_TYPE") == "listening":
ac_type = discord.ActivityType.listening
elif self.confmgr.get("DEFAULT_STATUS_TYPE") == "streaming":
ac_type = discord.ActivityType.streaming
total = 0
if "{number_users}" in self.confmgr.get("DEFAULT_STATUS_TEXT"):
guilds = self.bot.guilds
for guild in guilds:
total += guild.member_count
if ac_type is None:
ac_type = discord.ActivityType.playing
await self.bot.change_presence(
activity=discord.Activity(
type=ac_type,
name=self.confmgr.get("DEFAULT_STATUS_TEXT")
.replace("{guild_count}", str(len(list(self.bot.guilds))))
.replace("{number_users}", str(total)),
)
)
@commands.Cog.listener()
async def on_ready(self):
syslog.log("Bot Status", "Setting default status as per config")
await self.setDefaultStatus()
@tasks.loop(seconds=60.0)
async def status_task(self):
await self.setDefaultStatus()
@status_task.before_loop
async def before_status_task(self):
syslog.log(
"Bot Status", "Waiting for bot to be ready before starting updater task"
)
await self.bot.wait_until_ready()
syslog.log("Bot Status", "Bot is ready. Enabling update task")
@tasks.loop(seconds=1.0)
async def uptime_logger(self):
self.upt += 1
@uptime_logger.before_loop
async def before_logger_task(self):
await self.bot.wait_until_ready()
@commands.command(aliases=["uptime"])
async def getuptime(self, ctx):
await ctx.send(
embed=infmsg(
"Bot Stats",
"Uptime: `" + str(datetime.timedelta(seconds=self.upt)) + "`",
)
)
def setup(bot):
bot.add_cog(Status(bot))

@ -1,48 +0,0 @@
# This is a comment!
# Note: In the code, if the data type is not supported,
# you'll have to deal yourself (by editing global_config.py likely)
# Also, at the moment, these aren't type safe, so if you use this file in other cogs,
# make sure to use the correct getter function for the type you expect it to be. (and cast!)
# General bot stuff
# Types: watching, listening, playing
DEFAULT_STATUS_TYPE:watching
# These are currently the only substitutions
# - {number_users}
# - {guild_count}
DEFAULT_STATUS_TEXT:for ;
# Any default cogs you don't want to load:
# Example: UNLOAD_COGS:Internet,Speak
# Or maybe more likely: UNLOAD_COGS:Shells
# Blank is fine, too
UNLOAD_COGS:
# Who gets all log messages, and run extra-privileged commands
OWNER:117445905572954121
# Text for messages:
# Note {command} is the only substitution allowed here (we do auto-mention the user)
WRONG_PERMS:You're not a special snowflake, so you can't run `{command}`
# Should the owner get a DM when the bot restarts
OWNER_DM_RESTART:True
######################################################################################
# Package settings #
######################################################################################
# Package names to care about
WATCHED_PACKAGES:grub,arch-install-scripts,base,filesystem,lsb-release,neofetch,pfetch
# How often to re-query the feed(s) {in seconds}
REFRESH_TIME:3600
# Feed source(s)
FEED_URLS:archlinux.org/feeds/packages/
# Channel to send notifications
PACKAGE_CHANNEL:900844916974977125

@ -1,99 +0,0 @@
import os
# Nonstandard to avoid depend loop
from logger import BotLogger
syslog = BotLogger("system_log.txt")
def check(fn):
if os.path.exists(fn):
return True
else:
return False
class configboi:
def __init__(self, fn, logging=True):
self.config = {}
if not check(fn):
if logging:
syslog.log("Config", "No config found!")
else:
if logging:
syslog.log("Config", "----- Loading config values -----")
with open(fn) as f:
config_lines = f.read().split("\n")
for line in config_lines:
if line != "" and line != "\n":
if line[0] != "#":
bits = line.split(":")
key = bits[0]
val = bits[1]
if logging:
syslog.log("Config", "Added " + key + ": " + val)
self.config[key] = val
self.islogging = logging
def reloadconfig(self):
if not check(fn):
if self.logging:
syslog.log("Config", "No config found!")
else:
if self.logging:
syslog.log("Config", "----- Loading config values -----")
with open(fn) as f:
config_lines = f.read().split("\n")
for line in config_lines:
if line != "" and line != "\n":
if line[0] != "#":
bits = line.split(":")
key = bits[0]
val = bits[1]
if self.logging:
syslog.log("Config", "Added " + key + ": " + val)
self.config[key] = val
def get(self, key):
if key in self.config:
return self.config[key].replace("//", "://")
else:
return "Not found"
def getasint(self, key):
if key in self.config:
return int(self.config[key])
else:
return 0
def getasbool(self, key):
if key in self.config:
result = self.config[key]
if result == "true" or result == "True":
return True
else:
return False
else:
return False
def getaslist(self, key):
if key in self.config:
if "," in self.config[key]:
return self.config[key].split(",")
else:
return [self.config[key]]
else:
return None
def getasintlist(self, key):
if key in self.config:
if "," in self.config[key]:
data = self.config[key].split(",")
newdata = []
for item in data:
newdata.append(int(item))
return newdata
else:
return [int(self.config[key])]
else:
return [0]

@ -1,31 +0,0 @@
import os
def getstamp():
os.system("date >> stamp")
with open("stamp") as f:
s = f.read()
os.remove("stamp")
return s
class BotLogger:
def __init__(self, filename):
if os.path.exists(filename):
n = 0
while os.path.exists(filename + "." + str(n)):
n += 1
filename = filename + "." + str(n)
self.fn = filename
def log(self, caller, text):
info = getstamp().strip() + " --> " + caller + ": " + text
with open(self.fn, "a+") as f:
f.write("\n" + info + "\n")
print(info)
def getlog(self):
with open(self.fn) as f:
return f.read()

@ -1,6 +1,2 @@
py-cord[voice]
discord-pretty-help
requests
asyncio
requests
feedparser
py-cord

@ -0,0 +1,69 @@
from discord.ext import tasks, commands
import feedparser,os
CHAN = 825480016045408329
ROLE = 825474723948265474
WATCHED = "grub,arch-install-scripts,base,filesystem,lsb-release,neofetch,pfetch"
class Package:
def __init__(self,name,ver,arch):
self.name = name
self.ver = ver
self.arch = arch
def __str__(self):
return self.name + ' ' + self.ver + ' ' + self.arch
def __repr__(self):
return self.__str__()
class Packages(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.check.start()
if not os.path.exists("packages"):
os.makedirs("packages")
def cog_unload(self):
self.check.cancel()
@tasks.loop(seconds=300)
async def check(self):
watched = WATCHED.split(",")
new = []
feed_data = feedparser.parse('https://archlinux.org/feeds/packages/')
for entry in feed_data.entries:
info = entry.title
name,version,arch = info.split(" ")
if name in watched:
p = Package(name,version,arch)
new.append(p)
for p in new:
if os.path.exists("packages/" + p.name):
ver = open("packages/" + p.name, "r").read()
if ver != p.ver:
os.remove("packages/" + p.name)
with open("packages/" + p.name, "w") as f:
f.write(p.ver)
else:
new.pop(p)
else:
with open("packages/" + p.name, "w") as f:
f.write(p.ver)
if new != []:
await self.bot.get_channel(CHAN).send("<@&" + str(ROLE) + ">, there are package changes.")
for p in new:
print(str(p))
print("-"*10)
msg = "`" + p.name + "` is now `" + p.ver + "`"
await self.bot.get_channel(CHAN).send(msg)
#else:
# await self.bot.get_channel(CHAN).send("No new packages")
@check.before_loop
async def before_check(self):
print('waiting for bot to be ready...')
await self.bot.wait_until_ready()

@ -1,141 +0,0 @@
# System
import os, sys, random, string
# Pip
import asyncio, requests, discord
# Me
from global_config import configboi
from logger import BotLogger
# lol
confmgr = configboi("config.txt", False)
syslog = BotLogger("system_log.txt")
# <-------------- Don't touch pls --------------->
# If you're adding your own stuff, you need to look at
# global_config.py to see the supported data types, and add your
# own if needed.
# .get is string
VER = confmgr.get("VER")
HELP_LOC = confmgr.get("HELP_LOC")
WRONG_PERMS = confmgr.get("WRONG_PERMS")
NEW_MEMBER = confmgr.get("NEW_MEMBER")
INTRO_CHANNEL = confmgr.get("INTRO_CHANNEL")
DEFAULT_STATUS_TYPE = confmgr.get("DEFAULT_STATUS_TYPE")
DEFAULT_STATUS_TEXT = confmgr.get("DEFAULT_STATUS_TEXT")
UNLOAD_COGS = confmgr.getaslist("UNLOAD_COGS")
OWNER = confmgr.getasint("OWNER")
# <-------------- End --------------------->
# <--------------Colors Start-------------->
# For embed msgs (you can override these if you want)
# But changing the commands which use embed would be better
purple_dark = 0x6A006A
purple_medium = 0xA958A5
purple_light = 0xC481FB
orange = 0xFFA500
gold = 0xDAA520
red_dark = 8e2430
red_light = 0xF94343
blue_dark = 0x3B5998
cyan = 0x5780CD
blue_light = 0xACE9E7
aqua = 0x33A1EE
pink = 0xFF9DBB
green_dark = 0x2AC075
green_light = 0xA1EE33
white = 0xF9F9F6
cream = 0xFFDAB9
# <--------------Colors End-------------->
def strip_dangerous(text):
remove = [";", "&&", "&", '"']
for thing in remove:
text = text.replace(thing, "")
if "\n" in text:
text = text.split("\n")[0]
return text
def fancymsg(title, text, color, footnote=None):
e = discord.Embed(colour=color)
e.add_field(name=title, value=text, inline=False)
if footnote is not None:
e.set_footer(text=footnote)
return e
def errmsg(title, text, footnote=None):
return fancymsg(title, text, discord.Colour.red(), footnote)
def warnmsg(title, text, footnote=None):
return fancymsg(title, text, discord.Colour.gold(), footnote)
def infmsg(title, text, footnote=None):
return fancymsg(title, text, discord.Colour.blurple(), footnote)
def imgbed(title, type, dat):
# see https://discordpy.readthedocs.io/en/stable/faq.html?highlight=embed#how-do-i-use-a-local-image-file-for-an-embed-image
e = discord.Embed(color=discord.Colour.blurple())
e.add_field(name="foo", value=title, inline=False)
if type == "rem":
e.set_image(url=dat)
else:
e.set_image(url="attachment://" + dat)
return e
# Simple file wrappers
def check(fn):
if os.path.exists(fn):
return True
else:
return False
def save(fn, text):
with open(fn, "a+") as f:
f.write(text + "\n")
def get(fn):
if check(fn):
with open(fn) as f:
return f.read()
def ensure(fn):
if not check(fn):
os.makedirs(fn, exist_ok=True)
def getstamp():
if sys.platform != "win32":
os.system("date >> stamp")
with open("stamp") as f:
s = f.read()
os.remove("stamp")
return s
else:
return ""
def wrongperms(command):
syslog.log("System", "Someone just failed to run: '" + command + "'")
return WRONG_PERMS.replace("{command}", command)
def fail(msg):
syslog.log("System ERROR", msg)
sys.exit(1)
Loading…
Cancel
Save