Compare commits

..

19 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
31bd289f32 Fail safely if not in secure.http_mods or trusted_mods 2019-01-22 19:05:04 +05:30
4dee25a43b Add lua mod 2019-01-22 18:59:16 +05:30
5 changed files with 216 additions and 10 deletions

View File

@@ -1,2 +1,23 @@
# 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 logging
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 - \
%(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):
print("in here")
if update.message.chat.id in config.groups:
print("in here")
for i in update.message.text.split("\n"):
params = {"message": (f"TG - {update.message.from_user.first_name}"
f": {i}")}
requests.post("http://localhost:" + str(config.port) + "/post",
data=params)
print(params)
message = get_text_or_type(update.message, bot)
params = {"message": demojize(message)}
requests.post("http://localhost:" + str(config.port) + "/post",
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",
data=params)
updater = Updater(token=config.api_key)
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()

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
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):
@@ -25,8 +35,23 @@ def post(db):
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__)
db = sqlite3.connect(":memory:", check_same_thread=False)
bot = telegram.Bot(token=config.api_key)
# Set up tables
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('/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"])

72
chat_mod/init.lua Normal file
View File

@@ -0,0 +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)
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)
end
end
end
function main()
port = minetest.settings:get("chat_server_port")
if port == nil then
port = "9876"
end
http_api.fetch({url = "http://localhost:" .. port .. "/get"}, send_messages)
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
if http_api == nil then
minetest.log("error", "Chat Mod is not in secure.http_mods or secure.trusted_mods. Exiting.")
else
main()
end
minetest.register_on_dieplayer(dead)
minetest.register_on_joinplayer(join)
minetest.register_on_leaveplayer(left)
minetest.register_on_chat_message(chat)