Compare commits
	
		
			21 Commits
		
	
	
		
			68a4d440e6
			...
			master
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 149ab033b0 | |||
| f3b74b65ed | |||
| 17eb4e8bdd | |||
| 7bdebb7fd3 | |||
| bb9a9f7a9b | |||
| 0434bf5854 | |||
| 0238610cd1 | |||
| c4afd9139e | |||
| a9ed7aa159 | |||
| 489dccaa4e | |||
| 47592d5c44 | |||
| 2d377081b6 | |||
| a5ed267b32 | |||
| e075c24306 | |||
| 7639027684 | |||
| 1632bbfbe2 | |||
| a982ee0525 | |||
| 31bd289f32 | |||
| 4dee25a43b | |||
| f88e29426d | |||
| d7c4f7e14c | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -114,3 +114,4 @@ dmypy.json | ||||
| # Pyre type checker | ||||
| .pyre/ | ||||
|  | ||||
| config.py | ||||
|   | ||||
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
								
							| @@ -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. | ||||
|   | ||||
							
								
								
									
										99
									
								
								bot/bot.py
									
									
									
									
									
								
							
							
						
						
									
										99
									
								
								bot/bot.py
									
									
									
									
									
								
							| @@ -1,13 +1,106 @@ | ||||
| #!/usr/bin/env python3 | ||||
|  | ||||
| import config | ||||
| from telegram.ext import Updater, MessageHandler, Filters | ||||
| import logging | ||||
| import requests | ||||
| 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): | ||||
|     pass | ||||
|     if update.message.chat.id in config.groups: | ||||
|         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
									
								
							
							
						
						
									
										7
									
								
								bot/pipe_in.py
									
									
									
									
									
										Executable 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="") | ||||
| @@ -4,3 +4,6 @@ api_key = "123456789:xxxxxxxxxxxxxxxxxxxxxxxxxxxx" | ||||
|  | ||||
| # Port to connect to server | ||||
| port = 9876 | ||||
|  | ||||
| # Groups to read from | ||||
| groups = [] | ||||
|   | ||||
| @@ -1,19 +1,57 @@ | ||||
| #!/usr/bin/env python3 | ||||
|  | ||||
| from flask import Flask | ||||
| from flask import Flask, request | ||||
| import sqlite3 | ||||
| import config | ||||
| import telegram | ||||
| import re | ||||
| from emoji import emojize | ||||
|  | ||||
|  | ||||
| def escape_html(message): | ||||
|     return re.sub("<", "<", | ||||
|                   re.sub(">", "&rt;", | ||||
|                          re.sub("&", "&", message))) | ||||
|  | ||||
|  | ||||
| def get(db): | ||||
|     pass | ||||
|     cursor = db.cursor() | ||||
|     query = "SELECT * FROM messages ORDER BY ROWID" | ||||
|     cursor.execute(query) | ||||
|     text = "" | ||||
|     for row in cursor: | ||||
|         text += row[0] + "\n" | ||||
|     cursor.execute("DELETE FROM messages") | ||||
|     db.commit() | ||||
|     return text | ||||
|  | ||||
|  | ||||
| def post(db): | ||||
|     pass | ||||
|     message = request.form['message'] | ||||
|     cursor = db.cursor() | ||||
|     query = 'INSERT INTO messages values(?)' | ||||
|     cursor.execute(query, (message,)) | ||||
|     db.commit() | ||||
|     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() | ||||
| @@ -21,4 +59,6 @@ with open('schema.sql') as fp: | ||||
|     cursor.executescript(fp.read()) | ||||
|  | ||||
| app.add_url_rule('/get', 'get', lambda: get(db)) | ||||
| app.add_url_rule('/post', 'post', lambda: post(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
									
								
							
							
						
						
									
										72
									
								
								chat_mod/init.lua
									
									
									
									
									
										Normal 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) | ||||
		Reference in New Issue
	
	Block a user