From fcfc716b92d8c874e739931ee56e76c53dc4d854 Mon Sep 17 00:00:00 2001 From: dgw Date: Thu, 15 Jun 2023 21:59:13 -0500 Subject: [PATCH] meetbot: remove in favor of external package This change leaves the references to `meetbot` in documentation for how to use the plugin-related settings in the bot's `core` config section, as they're just examples. No real reason to change them. --- sopel/modules/meetbot.py | 564 --------------------------------------- 1 file changed, 564 deletions(-) delete mode 100644 sopel/modules/meetbot.py diff --git a/sopel/modules/meetbot.py b/sopel/modules/meetbot.py deleted file mode 100644 index 542c1cea60..0000000000 --- a/sopel/modules/meetbot.py +++ /dev/null @@ -1,564 +0,0 @@ -""" -meetbot.py - Sopel Meeting Logger Plugin -This plugin is an attempt to implement some of the functionality of Debian's meetbot -Copyright © 2012, Elad Alfassa, -Licensed under the Eiffel Forum License 2. - -https://sopel.chat -""" -from __future__ import annotations - -import codecs -import collections -import os -import re -from string import punctuation, whitespace -import time -from typing import Dict - -from sopel import formatting, plugin, tools -from sopel.config import types -from sopel.modules.url import find_title - - -UNTITLED_MEETING = "Untitled meeting" - - -class MeetbotSection(types.StaticSection): - """Configuration file section definition""" - - meeting_log_path = types.FilenameAttribute( - "meeting_log_path", - relative=False, - directory=True, - default="~/www/meetings") - """Path to meeting logs storage directory. - - This should be an absolute path, accessible on a webserver. - """ - - meeting_log_baseurl = types.ValidatedAttribute( - "meeting_log_baseurl", - default="http://localhost/~sopel/meetings") - """Base URL for the meeting logs directory.""" - - -def configure(config): - """ - | name | example | purpose | - | ---- | ------- | ------- | - | meeting\\_log\\_path | /home/sopel/www/meetings | Path to meeting logs storage directory (should be an absolute path, accessible on a webserver) | - | meeting\\_log\\_baseurl | http://example.com/~sopel/meetings | Base URL for the meeting logs directory | - """ - config.define_section("meetbot", MeetbotSection) - config.meetbot.configure_setting( - "meeting_log_path", "Enter the directory to store logs in." - ) - config.meetbot.configure_setting( - "meeting_log_baseurl", "Enter the base URL for the meeting logs." - ) - - -def setup(bot): - bot.config.define_section("meetbot", MeetbotSection) - - -meetings_dict: Dict[str, dict] = collections.defaultdict(dict) # Saves metadata about currently running meetings -""" -meetings_dict is a 2D dict. - -Each meeting should have: -channel -time of start -head (can stop the meeting, plus all abilities of chairs) -chairs (can add infolines to the logs) -title -current subject -comments (what people who aren't voiced want to add) - -Using channel as the meeting ID as there can't be more than one meeting in a -channel at the same time. -""" - -# To be defined on meeting start as part of sanity checks, used by logging -# functions so we don't have to pass them bot -meeting_log_path = "" -meeting_log_baseurl = "" - -# A dict of channels to the actions that have been created in them. This way -# we can have .listactions spit them back out later on. -meeting_actions = {} - - -# Get the logfile name for the meeting in the requested channel -# Used by all logging functions and web path -def figure_logfile_name(channel): - if meetings_dict[channel]["title"] == UNTITLED_MEETING: - name = "untitled" - else: - name = meetings_dict[channel]["title"] - # Real simple sluggifying. - # May not handle unicode or unprintables well. Close enough. - for character in punctuation + whitespace: - name = name.replace(character, "-") - name = name.strip("-") - timestring = time.strftime( - "%Y-%m-%d-%H:%M", time.gmtime(meetings_dict[channel]["start"]) - ) - filename = timestring + "_" + name - return filename - - -# Start HTML log -def log_html_start(channel): - logfile_filename = os.path.join( - meeting_log_path + channel, figure_logfile_name(channel) + ".html" - ) - logfile = codecs.open(logfile_filename, "a", encoding="utf-8") - timestring = time.strftime( - "%Y-%m-%d %H:%M", time.gmtime(meetings_dict[channel]["start"]) - ) - title = "%s at %s, %s" % (meetings_dict[channel]["title"], channel, timestring) - logfile.write( - ( - "\n" - "{title}\n\n

{title}

\n" - ).format(title=title) - ) - logfile.write( - "

Meeting started by %s

\n

Meeting ended at %s UTC

\n" % current_time) - plainlog_url = meeting_log_baseurl + tools.web.quote( - channel + "/" + figure_logfile_name(channel) + ".log" - ) - logfile.write('Full log' % plainlog_url) - logfile.write("\n\n\n") - logfile.close() - - -# Write a string to the plain text log -def log_plain(item, channel): - logfile_filename = os.path.join( - meeting_log_path + channel, figure_logfile_name(channel) + ".log" - ) - logfile = codecs.open(logfile_filename, "a", encoding="utf-8") - current_time = time.strftime("%H:%M:%S", time.gmtime()) - logfile.write("[" + current_time + "] " + item + "\r\n") - logfile.close() - - -# Check if a meeting is currently running -def is_meeting_running(channel): - try: - return meetings_dict[channel]["running"] - except KeyError: - return False - - -# Check if nick is a chair or head of the meeting -def is_chair(nick, channel): - try: - return ( - nick.lower() == meetings_dict[channel]["head"] or - nick.lower() in meetings_dict[channel]["chairs"] - ) - except KeyError: - return False - - -# Start meeting (also performs all required sanity checks) -@plugin.command("startmeeting") -@plugin.example(".startmeeting", user_help=True) -@plugin.example(".startmeeting Meeting Title", user_help=True) -@plugin.require_chanmsg("Meetings can only be started in channels") -def startmeeting(bot, trigger): - """ - Start a meeting.\ - See [meetbot plugin usage]({% link _usage/meetbot-plugin.md %}) - """ - if is_meeting_running(trigger.sender): - bot.say("There is already an active meeting here!") - return - # Start the meeting - meetings_dict[trigger.sender]["start"] = time.time() - if not trigger.group(2): - meetings_dict[trigger.sender]["title"] = UNTITLED_MEETING - else: - meetings_dict[trigger.sender]["title"] = trigger.group(2) - meetings_dict[trigger.sender]["head"] = trigger.nick.lower() - meetings_dict[trigger.sender]["running"] = True - meetings_dict[trigger.sender]["comments"] = [] - - # Set up paths and URLs - global meeting_log_path - meeting_log_path = bot.config.meetbot.meeting_log_path - if not meeting_log_path.endswith(os.sep): - meeting_log_path += os.sep - - global meeting_log_baseurl - meeting_log_baseurl = bot.config.meetbot.meeting_log_baseurl - if not meeting_log_baseurl.endswith("/"): - meeting_log_baseurl = meeting_log_baseurl + "/" - - channel_log_path = meeting_log_path + trigger.sender - if not os.path.isdir(channel_log_path): - try: - os.makedirs(channel_log_path) - except Exception: # TODO: Be specific - bot.say( - "Meeting not started: Couldn't create log directory for this channel" - ) - meetings_dict[trigger.sender] = collections.defaultdict(dict) - raise - # Okay, meeting started! - log_plain("Meeting started by " + trigger.nick.lower(), trigger.sender) - log_html_start(trigger.sender) - meeting_actions[trigger.sender] = [] - bot.say( - ( - formatting.bold("Meeting started!") + " use {0}action, {0}agreed, " - "{0}info, {0}link, {0}chairs, {0}subject, and {0}comments to " - "control the meeting. To end the meeting, type {0}endmeeting" - ).format(bot.config.core.help_prefix) - ) - bot.say( - ( - "Users without speaking permission can participate by sending me " - "a PM with `{0}comment {1}` followed by their comment." - ).format(bot.config.core.help_prefix, trigger.sender) - ) - - -# Change the current subject (will appear as

in the HTML log) -@plugin.command("subject") -@plugin.example(".subject roll call") -def meetingsubject(bot, trigger): - """ - Change the meeting subject.\ - See [meetbot plugin usage]({% link _usage/meetbot-plugin.md %}) - """ - if not is_meeting_running(trigger.sender): - bot.say("There is no active meeting") - return - if not trigger.group(2): - bot.say("What is the subject?") - return - if not is_chair(trigger.nick, trigger.sender): - bot.say("Only meeting head or chairs can do that") - return - meetings_dict[trigger.sender]["current_subject"] = trigger.group(2) - logfile_filename = os.path.join( - meeting_log_path + trigger.sender, figure_logfile_name(trigger.sender) + ".html" - ) - logfile = codecs.open(logfile_filename, "a", encoding="utf-8") - logfile.write("

" + trigger.group(2) + "