Compare commits

..

17 Commits

Author SHA1 Message Date
149ab033b0 Add player count 2019-01-29 11:47:31 +05:30
f3b74b65ed Fix /list 2019-01-29 11:11:19 +05:30
17eb4e8bdd Fix replies to non-chat messages by bot 2019-01-29 10:19:56 +05:30
7bdebb7fd3 Move join/leave/chat messages to mod instead of parsing stderr 2019-01-29 09:57:16 +05:30
bb9a9f7a9b Remove list from join/leave messages 2019-01-29 03:03:45 +05:30
0434bf5854 Add /time 2019-01-29 02:57:31 +05:30
0238610cd1 Add /list 2019-01-29 02:05:39 +05:30
c4afd9139e Add death messages 2019-01-29 01:39:16 +05:30
a9ed7aa159 Fix escape_html 2019-01-28 23:49:54 +05:30
489dccaa4e Add /send and /sendCode endpoints 2019-01-28 21:35:27 +05:30
47592d5c44 Update README 2019-01-28 17:51:00 +05:30
2d377081b6 Add pipe_in.py to deal with minetest output 2019-01-28 17:49:06 +05:30
a5ed267b32 Change reply format. Demojize 2019-01-28 17:18:15 +05:30
e075c24306 Deal with all data types and replies. 2019-01-28 16:32:31 +05:30
7639027684 Update README 2019-01-23 00:15:52 +05:30
1632bbfbe2 Fix typo 2019-01-22 19:14:23 +05:30
a982ee0525 Update README.md 2019-01-22 19:13:30 +05:30
5 changed files with 200 additions and 15 deletions

View File

@@ -1,2 +1,23 @@
# minetest-telegram-bridge # minetest-telegram-bridge
# Usage
+ Install `python3`, `flask`, `python-telegram-bot`
+ `cd`
+ `git clone https://git.webionite.com/ceda_ei/minetest-telegram-bridge`
+ `ln -s ~/minetest-telegram-bridge/chat_mod ~/.minetest/mods/chat_mod`
+ Add mod to `secure.http_mods`.
+ Add this line if `secure.http_mods` doesn't exist. `secure.http_mods = chat_mod`
+ Enable the mod in `world.mt`
+ `cd minetest-telegram-bridge/bot`
+ Copy `sample.config.py` to `config.py` and edit.
+ `python3 bot.py &`
+ `export FLASK_APP=server.py`
+ `export FLASK_ENV=production`
+ `flask run -p 9876`
+ Start the minetest server via `minetest [params] |& python3 pipe_in.py`
# Configuration
To use a different port, change the respective config in `config.py` and add `chat_server_port = PORT` in `minecraft.conf` and run `flask run -p PORT` instead of the last step.

View File

@@ -3,25 +3,104 @@
import config import config
import logging import logging
import requests import requests
from telegram.ext import Updater, MessageHandler, Filters import re
from emoji import demojize
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - \ logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - \
%(message)s', level=logging.INFO) %(message)s', level=logging.INFO)
def get_text_or_type(msg, bot, truncate=False):
message = ""
# Set message contents
if msg.text:
if msg.from_user.username == bot.username and re.match('<.*?>(.*)',
msg.text):
x = re.compile('(<.*?>)(.*)')
y = x.search(msg.text)
z = y.group(2)
message += (z if len(z) <= 20 or not truncate else z[0:19] + "...")
else:
message += (msg.text if len(msg.text) <= 20 or not truncate else
msg.text[0:19] + "...")
elif msg.audio:
message += "[Audio]"
elif msg.document:
message += "[Document]"
elif msg.animation:
message += "[GIF]"
elif msg.game:
message += "[Game]"
elif msg.photo:
message += "[Photo]"
elif msg.sticker:
message += "[Sticker]"
elif msg.video:
message += "[Video]"
elif msg.voice:
message += "[Voice Note]"
elif msg.video_note:
message += "[Video Note]"
elif msg.contact:
message += "[Contact]"
elif msg.location:
message += "[Location]"
elif msg.venue:
message += "[Venue]"
else:
message += "[Unknown type]"
# If caption exists
if msg.caption:
message += (msg.caption if len(msg.caption) <= 20 or not truncate else
msg.caption[0:19] + "...")
# Set sender
return_message = ""
for i in message.strip().split("\n"):
if msg.from_user.username != bot.username or not re.match('<.*?>(.*)',
msg.text):
if msg.from_user.username:
return_message += f"@{msg.from_user.username}: "
else:
return_message += f"{msg.from_user.first_name}: "
else:
x = re.compile('(<.*?>)(.*)')
y = x.search(msg.text)
return_message = y.group(1) + ": " + i + "\n"
# Set the replied to message's contents
if msg.reply_to_message:
return_message += ("[> " +
get_text_or_type(msg.reply_to_message, bot,
True).split("\n")[0] +
f"] ")
return_message += i + "\n"
return return_message.strip()
def message_handling(bot, update): def message_handling(bot, update):
print("in here")
if update.message.chat.id in config.groups: if update.message.chat.id in config.groups:
print("in here") message = get_text_or_type(update.message, bot)
for i in update.message.text.split("\n"): params = {"message": demojize(message)}
params = {"message": (f"TG - {update.message.from_user.first_name}" requests.post("http://localhost:" + str(config.port) + "/post",
f": {i}")} data=params)
def direct_cmd(bot, update, text):
if update.message.chat.id in config.groups:
params = {"message": text}
requests.post("http://localhost:" + str(config.port) + "/post", requests.post("http://localhost:" + str(config.port) + "/post",
data=params) data=params)
print(params)
updater = Updater(token=config.api_key) updater = Updater(token=config.api_key)
dispatcher = updater.dispatcher dispatcher = updater.dispatcher
dispatcher.add_handler(MessageHandler(Filters.text, message_handling)) dispatcher.add_handler(CommandHandler('list', lambda x, y: direct_cmd(x, y,
"list")))
dispatcher.add_handler(CommandHandler('time', lambda x, y: direct_cmd(x, y,
"time")))
dispatcher.add_handler(MessageHandler(Filters.all, message_handling))
updater.start_polling() updater.start_polling()

7
bot/pipe_in.py Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env python3
import sys
import re
for line in sys.stdin:
if not re.match(".* Mod performs HTTP request with URL ", line):
print(line, end="")

View File

@@ -2,6 +2,16 @@
from flask import Flask, request from flask import Flask, request
import sqlite3 import sqlite3
import config
import telegram
import re
from emoji import emojize
def escape_html(message):
return re.sub("<", "&lt;",
re.sub(">", "&rt;",
re.sub("&", "&amp;", message)))
def get(db): def get(db):
@@ -25,8 +35,23 @@ def post(db):
return "" return ""
def send(bot, code):
message = request.form["message"]
if code:
message = escape_html(message)
message = "<code>" + message + "</code>"
for i in config.groups:
bot.send_message(chat_id=i, text=emojize(message),
parse_mode="HTML")
else:
for i in config.groups:
bot.send_message(chat_id=i, text=emojize(message))
return ""
app = Flask(__name__) app = Flask(__name__)
db = sqlite3.connect(":memory:", check_same_thread=False) db = sqlite3.connect(":memory:", check_same_thread=False)
bot = telegram.Bot(token=config.api_key)
# Set up tables # Set up tables
cursor = db.cursor() cursor = db.cursor()
@@ -35,3 +60,5 @@ with open('schema.sql') as fp:
app.add_url_rule('/get', 'get', lambda: get(db)) app.add_url_rule('/get', 'get', lambda: get(db))
app.add_url_rule('/post', 'post', lambda: post(db), methods=["POST"]) app.add_url_rule('/post', 'post', lambda: post(db), methods=["POST"])
app.add_url_rule('/send', 'send', lambda: send(bot, False), methods=["POST"])
app.add_url_rule('/sendCode', 'sc', lambda: send(bot, True), methods=["POST"])

View File

@@ -1,21 +1,72 @@
local http_api = minetest.request_http_api()
function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
function send_messages(res) function send_messages(res)
for message in string.gmatch(res["data"], "[^\n]+") do for message in string.gmatch(res["data"], "[^\n]+") do
if message == "list" then
local x = minetest.get_connected_players()
local text = "List of Players ("
text = text .. tostring(tablelength(x)) .. "/"
text = text .. tostring(minetest.settings:get("max_users")) .. "):"
for j, i in ipairs(x) do
text = text .. "\n" .. i.get_player_name(i)
end
http_api.fetch_async({url = "http://localhost:" .. port .. "/sendCode",
post_data = {message = text}})
elseif message == "time" then
local x = minetest.get_timeofday()
local text = string.format("%02d:%02d", math.floor(x*24), math.floor((x*24*60) % 60))
http_api.fetch_async({url = "http://localhost:" .. port .. "/sendCode",
post_data = {message = text}})
else
minetest.chat_send_all(message) minetest.chat_send_all(message)
end end
end
end end
function main(http_api) function main()
port = minetest.settings:get("chat_server_port") port = minetest.settings:get("chat_server_port")
if port == nil then if port == nil then
port = "9876" port = "9876"
end end
http_api.fetch({url = "http://localhost:" .. port .. "/get"}, send_messages) http_api.fetch({url = "http://localhost:" .. port .. "/get"}, send_messages)
minetest.after(0.5, main, http_api) minetest.after(0.5, main)
end
function dead(player)
http_api.fetch_async({url = "http://localhost:" .. port .. "/sendCode",
post_data = {message = player.get_player_name(player) ..
" died."}})
end
function join(player)
http_api.fetch_async({url = "http://localhost:" .. port .. "/sendCode",
post_data = {message = player.get_player_name(player) ..
" joined the server."}})
end
function left(player)
http_api.fetch_async({url = "http://localhost:" .. port .. "/sendCode",
post_data = {message = player.get_player_name(player) ..
" left the server."}})
end
function chat(name, message)
http_api.fetch_async({url = "http://localhost:" .. port .. "/send",
post_data = {message = "<" .. name .. "> " .. message}})
end end
local http_api = minetest.request_http_api()
if http_api == nil then if http_api == nil then
minetest.log("error", "Chat Mod is not in secure.http_mods or secure.trusted_mods. Exiting.") minetest.log("error", "Chat Mod is not in secure.http_mods or secure.trusted_mods. Exiting.")
else else
main(http_api) main()
end end
minetest.register_on_dieplayer(dead)
minetest.register_on_joinplayer(join)
minetest.register_on_leaveplayer(left)
minetest.register_on_chat_message(chat)