Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore unknown #31

Merged
merged 6 commits into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions pybliotecario.ini.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
[DEFAULT]
TOKEN = <telegram bot token>
chat_id = <chat_id number>
main_folder = /home/<username>/.pybliotecario

# chat_id accepts also a list of IDs separated by comma, the first one is considered the main one
chat_id = <chat_id number>
main_folder = /home/<username>/.local/share/pybliotecario
# quiet defaults to false, whether the bot should always reply back
quiet = false
# when chivato is true, the bot will write to the main chat_id whenever an user not in chat_id writes to the bot
chivato = false
# if true, messages from chat ids not included in `chat_id` will be ignored
ignore_unknown = false

[FACEBOOK]
verify = <verify token from fb>
Expand Down
3 changes: 2 additions & 1 deletion src/pybliotecario/argument_parser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Wrapper for the argument parser and the initialization
"""

from argparse import Action, ArgumentParser, ArgumentTypeError
import configparser
import glob
Expand Down Expand Up @@ -93,7 +94,7 @@ def configure_telegram():
token = input("Authorization token: ")

# Try to fire up the bot with the given token
telegram_API = TelegramUtil(token, timeout=20)
telegram_API = TelegramUtil(token=token, timeout=20)
print("Thanks, let's test this out. Say something (anything!) to your bot in telegram")

for _ in range(20): # Allow for 20 tries
Expand Down
16 changes: 15 additions & 1 deletion src/pybliotecario/backend/basic_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"""

from abc import ABC, abstractmethod
from configparser import ConfigParser
import json
import logging
import urllib
Expand Down Expand Up @@ -160,7 +161,14 @@ class Backend(ABC):

"""

_max_size = 99999
def __init__(self, config=None, debug=False, **kwargs):
if config is None:
# If no config is passed, generate and empty one
config = ConfigParser()
self._max_size = 99999
self._quiet = config.getboolean("DEFAULT", "quiet", fallback=False)
self._config = config
self._debug = debug

@abstractmethod
def _get_updates(self, not_empty=False):
Expand All @@ -175,6 +183,12 @@ def raw_updates(self):
def send_message(self, text, chat, **kwargs):
"""Sends a message to the chat"""

def send_quiet_message(self, text, chat, **kwargs):
"""Like ``send_message`` but only sends the message if quiet is set to False
otherwise, do nothing"""
if not self._quiet:
return self.send_message(text, chat, **kwargs)

@property
@abstractmethod
def _message_class(self):
Expand Down
29 changes: 22 additions & 7 deletions src/pybliotecario/backend/facebook_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,20 +79,31 @@ class FacebookUtil(Backend):
_message_class = FacebookMessage
_max_size = MAX_SIZE

def __init__(self, PAGE_TOKEN, VERIFY_TOKEN, host="0.0.0.0", port=3000, debug=False):
def __init__(self, config=None, host="0.0.0.0", port=3000, **kwargs):
super().__init__(config, **kwargs)
if config is None:
raise ValueError("A configuration with a FACEBOOK section must be given")

try:
fb_config = config["FACEBOOK"]
except KeyError:
raise ValueError("No facebook section found for facebook in pybliotecario.ini")

if not _HAS_FLASK:
# Raise the error now
raise ModuleNotFoundError("No module named 'flask'")
raise ModuleNotFoundError("No module named 'flask', needed for Facebook backend")

self.page_access_token = PAGE_TOKEN
self.verify_token = VERIFY_TOKEN
verify_token = fb_config.get("verify")
page_token = fb_config.get("app_token")

self.page_access_token = page_token
self.verify_token = verify_token
self.port = port
self.host = host
app = Flask(__name__)
# Load the listener into the webhook endpoint
app.add_url_rule("/webhook", "webhook", self.listener, methods=["POST", "GET"])
self.flask_app = app
self.debug = debug
self.action_function = None
self.auth = {"access_token": self.page_access_token}

Expand Down Expand Up @@ -121,7 +132,7 @@ def act_on_updates(self, action_function, not_empty=False):
opens the webhook to wait ofr updates and act on them
"""
self.action_function = action_function
self.flask_app.run(host=self.host, port=self.port, debug=self.debug)
self.flask_app.run(host=self.host, port=self.port, debug=self._debug)

def _get_updates(self, not_empty=False):
"""This class skips get_updates and uses act_on_updates directly"""
Expand Down Expand Up @@ -184,8 +195,12 @@ def send_file(self, filepath, chat):


if __name__ == "__main__":
from configparser import ConfigParser

logger.info("Testing FB Util")
verify = "your_verify_token"
app_token = "your_app_key"
fb_util = FacebookUtil(app_token, verify, debug=True)
config = ConfigParser()
config["FACEBOOK"] = {"verify": verify, "app_token": app_token}
fb_util = FacebookUtil(config, debug=True)
fb_util.act_on_updates(lambda x: print(x))
17 changes: 11 additions & 6 deletions src/pybliotecario/backend/telegram_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,18 @@ class TelegramUtil(Backend):

_message_class = TelegramMessage

def __init__(self, TOKEN, debug=False, timeout=300):
def __init__(self, config=None, token=None, timeout=300, **kwargs):
super().__init__(config, **kwargs)
if token is None:
if config is None:
raise ValueError("Either a config or a token must be provided for Telegram")
token = config.defaults().get("token")

self.offset = None
self.debug = debug
self.timeout = timeout
# Build app the API urls
base_URL = TELEGRAM_URL + f"bot{TOKEN}/"
self.base_fileURL = TELEGRAM_URL + f"file/bot{TOKEN}/"
base_URL = TELEGRAM_URL + f"bot{token}/"
self.base_fileURL = TELEGRAM_URL + f"file/bot{token}/"
self.send_msg = base_URL + "sendMessage"
self.send_img = base_URL + "sendPhoto"
self.send_doc = base_URL + "sendDocument"
Expand Down Expand Up @@ -185,7 +190,7 @@ def _get_updates(self, not_empty=False):
if not updates and not_empty:
return self._get_updates(not_empty=True)

if self.debug:
if self._debug:
logger.info("Request url: %s", url)
logger.info("Obtained updates: %s", updates)

Expand Down Expand Up @@ -254,7 +259,7 @@ def download_file(self, file_id, file_path):
if __name__ == "__main__":
logger.info("Testing TelegramUtil")
token = "must put a token here to test"
ut = TelegramUtil(token, debug=True)
ut = TelegramUtil(token=token, debug=True)
# noinspection PyProtectedMember
results = ut._get_updates()
for res in results:
Expand Down
13 changes: 11 additions & 2 deletions src/pybliotecario/components/component_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
the class Component will just pass the text of the msg (or the command)
to the `act_on_command` or `act_on_message` methods.
"""

import logging
import os
import sys
Expand Down Expand Up @@ -138,11 +139,15 @@ def act_on_command(self, content=None):
self.telegram.send_message("Command line argument invoked", self.chat_id)

# Some useful wrappers
def send_msg(self, msg, chat_id=None, markdown=False):
def send_msg(self, msg, chat_id=None, markdown=False, quiet=False):
"""Wrapper around API send_msg, if chat_id is not defined
it will use the chat_id this class was instantiated to"""
it will use the chat_id this class was instantiated to.
If ``quiet`` == True, use `send_quiet_message`
"""
if chat_id is None:
chat_id = self.interaction_chat
if quiet:
return self.telegram.send_quiet_message(msg, chat_id, markdown=markdown)
return self.telegram.send_message(msg, chat_id, markdown=markdown)

def send_img(self, imgpath, chat_id=None, delete=False):
Expand All @@ -168,3 +173,7 @@ def send_file(self, filepath, chat_id=None, delete=False):
self.telegram.send_file(filepath, chat_id)
if delete:
os.remove(filepath)

def _not_allowed_msg(self, chat_id=None):
"""Tell the calling ID they are not allowed to use this component"""
return self.send_msg("You are not allowed to use this", quiet=True, chat_id=chat_id)
1 change: 1 addition & 0 deletions src/pybliotecario/components/dnd.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Module implementing some functions useful for playing DnD over the internet
"""

import logging
from random import randint
import re
Expand Down
1 change: 1 addition & 0 deletions src/pybliotecario/components/github_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
and follow the instructions
"""

import datetime
import logging

Expand Down
8 changes: 4 additions & 4 deletions src/pybliotecario/components/ip_lookup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
""" Server-helper function to look up the current IP of the program """

import logging
import urllib.request

Expand All @@ -24,10 +25,9 @@ class IpLookup(Component):
def telegram_message(self, msg):
"""If the chat id asking is the correct one
sends a msg with the current ip, otherwise fails"""
if self.check_identity(msg):
send_msg = ip_lookup()
else:
send_msg = "You are not allowed to see this"
if not self.check_identity(msg):
return self._not_allowed_msg()
send_msg = ip_lookup()
self.telegram.send_message(send_msg, msg.chat_id)

def cmdline_command(self, args):
Expand Down
4 changes: 2 additions & 2 deletions src/pybliotecario/components/photocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

It's a companion to https://github.com/scarlehoff/websito/blob/master/views/foto.pug
"""

from datetime import datetime
import json
import logging
Expand Down Expand Up @@ -106,8 +107,7 @@ def telegram_message(self, msg):
return self.send_msg("Command not understood")

if not self.check_identity(msg):
self.send_msg("You are not allowed to interact with this command!")
return
return self._not_allowed_msg()

if msg.command == "photocol_remove":
return self._remove_from_db(msg.text)
Expand Down
21 changes: 10 additions & 11 deletions src/pybliotecario/components/pid.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,16 @@ def alive(pid):
return is_it_alive(pid)

def telegram_message(self, msg):
if self.check_identity(msg):
pid_string = msg.text.strip()
if msg.command == "kill_pid":
if pid_string.isdigit():
return_msg = self.kill(int(pid_string))
else:
return_msg = f"{pid_string} is not a PID?"
elif msg.command == "is_pid_alive":
return_msg = self.alive(pid_string)
if not self.check_identity(msg):
return self._not_allowed_msg
pid_string = msg.text.strip()
if msg.command == "kill_pid":
if pid_string.isdigit():
return_msg = self.kill(int(pid_string))
else:
return_msg = f"Command {msg.command} not understood?"
return_msg = f"{pid_string} is not a PID?"
elif msg.command == "is_pid_alive":
return_msg = self.alive(pid_string)
else:
return_msg = "You are not allowed to use this"
return_msg = f"Command {msg.command} not understood?"
self.send_msg(return_msg)
5 changes: 3 additions & 2 deletions src/pybliotecario/components/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
For instant, good_morning will call the command defined in
/script good_morning will call the command defined in [SCRIPTS] good_morning
"""

import logging
import pathlib
import shlex
Expand Down Expand Up @@ -121,7 +122,7 @@ def configure_me(cls):
def telegram_message(self, msg):
if not self.check_identity(msg) and not self._allow_everyone:
self.blocked = True
self.send_msg("You are not allowed to run scripts here")
self._not_allowed_msg()
if self.blocked:
return

Expand All @@ -148,7 +149,7 @@ def telegram_message(self, msg):
else:
cmd_list = [f"./{command_path.name}"] + script_args
sp.run(cmd_list, check=True, cwd=command_path.parent)
self.send_msg("Command ran")
self.send_msg("Command ran", quiet=True)
except sp.CalledProcessError:
self.send_msg("Command ran but failed")
else:
Expand Down
1 change: 1 addition & 0 deletions src/pybliotecario/components/stocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},

"""

import json
import logging

Expand Down
4 changes: 2 additions & 2 deletions src/pybliotecario/components/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This component contains system-commands to be run
remotely
"""

import subprocess as sp

from pybliotecario.components.component_core import Component
Expand Down Expand Up @@ -32,8 +33,7 @@ def __init__(self, telegram_object, **kwargs):
def telegram_message(self, msg):
# Allow only the main user to use system
if not self.check_identity(msg):
self.send_msg("You are not allowed to run scripts here")
return
return self._not_allowed_msg()
command_key = msg.text.strip()
command_name = ACCEPTED_COMMANDS.get(command_key)
# Check whether the command is in the accepted_commands dictionary
Expand Down
1 change: 1 addition & 0 deletions src/pybliotecario/components/twitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
consumer_secret = <consumer_secret>
```
"""

import logging

import tweepy as tw
Expand Down
Loading
Loading