Cree su propio servicio de envío de mensajes, admita múltiples métodos de envío de mensajes, admita Markdown, solo un archivo ejecutable, listo para usar de inmediato.
Descarga del programa·Tutorial de implementación·Tutorial de uso·Comentarios·Demostración en línea
Nota : El sitio de implementación oficial https://msgpusher.com ya está en línea y el registro está abierto. Bienvenido a usarlo. Si recibe comentarios positivos, puede considerar cambiar a un servidor con menor latencia en el futuro.
Advertencia : la actualización de
v0.3
av0.4
requiere la migración manual de la base de datos. Para obtener más información, consulte Migración de la base de datos.
Implementación: docker run -d --restart always --name message-pusher -p 3000:3000 -e TZ=Asia/Shanghai -v /home/ubuntu/data/message-pusher:/data justsong/message-pusher
Si no se puede extraer, reemplace justsong/message-pusher
con ghcr.io/songquanpeng/message-pusher
.
Actualización: docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR
El número de puerto abierto es 3000. Luego use Nginx para configurar el nombre de dominio, la generación inversa y el certificado SSL. Consulte el tutorial de implementación detallado para obtener más detalles.
Los datos se guardarán en el directorio /home/ubuntu/data/message-pusher
de la máquina host (solo hay un archivo de base de datos SQLite). Asegúrese de que el directorio exista y tenga permiso de escritura, o cámbielo a un directorio adecuado. .
Configuración de referencia de Nginx:
server{
server_name msgpusher.com; # 请根据实际情况修改你的域名
location / {
client_max_body_size 64m;
proxy_http_version 1.1;
proxy_pass http://localhost:3000; # 请根据实际情况修改你的端口
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_cache_bypass $http_upgrade;
proxy_set_header Accept-Encoding gzip;
}
}
Luego use el certbot de Let's Encrypt para configurar HTTPS:
# Ubuntu 安装 certbot:
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
# 生成证书 & 修改 Nginx 配置
sudo certbot --nginx
# 根据指示进行操作
# 重启 Nginx
sudo service nginx restart
git clone https://github.com/songquanpeng/message-pusher.git
cd message-pusher/web
npm install
npm run build
cd ..
go mod download
go build -ldflags " -s -w " -o message-pusher
chmod u+x message-pusher
./message-pusher --port 3000 --log-dir ./logs
root
y la contraseña es 123456
.Si el servicio necesita ejecutarse durante mucho tiempo, simplemente iniciarlo no es suficiente. Tutorial de implementación detallado.
Si necesita utilizar la función de inserción del cliente WebSocket, proxy_read_timeout
y proxy_send_timeout
en el archivo de configuración de Nginx deben configurarse en más de 1 minuto.
Configuraciones recomendadas:
proxy_read_timeout 300s;
proxy_send_timeout 300s;
El propio sistema sólo necesita descargar un archivo ejecutable para empezar a utilizarlo, sin otras dependencias.
Puede configurarlo configurando variables de entorno o parámetros de línea de comando.
Después de que se inicie el sistema, utilice el usuario root
para iniciar sesión en el sistema y realizar más configuraciones. La contraseña predeterminada es 123456
.
REDIS_CONN_STRING
: Después de la configuración, Redis se usará como almacenamiento para el límite de frecuencia de solicitud en lugar de usar almacenamiento de memoria.REDIS_CONN_STRING=redis://default:redispw@localhost:49153
SESSION_SECRET
: Después de la configuración, se utilizará una clave de sesión fija, de modo que la cookie del usuario que inició sesión seguirá siendo válida después de reiniciar el sistema.SESSION_SECRET=random_string
SQL_DSN
: después de la configuración, se utilizará la base de datos especificada en lugar de SQLite.SQL_DSN=root:123456@tcp(localhost:3306)/message-pusher
Nota: Al implementar con Docker, utilice -e key=value
para configurar las variables de entorno.
Ejemplo: docker run -e SESSION_SECRET=random_string ...
--port <port_number>
: especifique el número de puerto que escucha el servidor; el valor predeterminado es 3000
.--port 3000
--log-dir <log_dir>
: especifique la carpeta de registro. Si no se establece, el registro no se guardará.--log-dir ./logs
--version
: imprime el número de versión del sistema y sale.允许新用户注册
.更新用户信息
para cambiar el nombre de usuario y la contraseña predeterminados.绑定邮箱地址
para vincular el correo electrónico y habilitar el envío de mensajes de correo electrónico.默认推送方式
. El valor predeterminado es el envío por correo electrónico.推送token
para la autenticación de llamada de API de inserción. Déjelo en blanco si no es necesario.测试
correspondiente para probar si la configuración es exitosa.https://<domain>/push/<username>
<domain>
y <username>
anteriores con valores reales, por ejemplo: https://push.mydomain.cn/push/admin
GET
: https://<domain>/push/<username>?title=<标题>&description=<描述>&content=<Markdown 文本>&channel=<推送方式>&token=<推送token>
title
: Opcional, limitado por el método de envío de mensajes específico, puede ignorarse.description
: requerido, puede ser reemplazado por desp
.content
: opcional, limitado por el método de envío de mensajes específico, la compatibilidad con la sintaxis de Markdown es diferente.channel
: Opcional, si no se completa, el sistema usará el canal de inserción predeterminado que configuró en segundo plano. Tenga en cuenta que aquí se completa el nombre del canal de mensajes, no el tipo. Los tipos de canales de empuje opcionales son:email
: empuje enviando un correo electrónico (use el campo title
o description
para configurar el asunto del correo electrónico, use content
para configurar el cuerpo y admita la sintaxis completa de Markdown).test
: avance a través de la cuenta de prueba de WeChat (use el campo description
para configurar el contenido del mensaje de la plantilla, Markdown no es compatible).corp_app
: empuje a través de la cuenta de la aplicación WeChat empresarial (solo cuando se usa la aplicación WeChat empresarial, si el campo content
está configurado, title
y description
se ignorarán; es normal cuando se usa el complemento WeChat empresarial en WeChat).lark_app
: impulsa la aplicación de creación propia de Feishu.corp
: impulsado a través del robot del grupo empresarial WeChat (configurar el campo content
mostrará mensajes de Markdown, admitiendo un subconjunto de Markdown; configurar description
mostrará mensajes de texto normales).lark
: empujar a través del robot Feishuqun (las notas son las mismas que las anteriores).ding
: empujar a través del robot del grupo DingTalk (las notas son las mismas que las anteriores).bark
: presione Bark (admite campos title
y description
).client
: envío a través del cliente WebSocket (admite campos title
y description
).telegram
: envío a través del robot de Telegram (elija uno de los campos description
o content
, admite un subconjunto de Markdown).discord
: empuja el bot del grupo Discord (las notas son las mismas que las anteriores).one_api
: envía mensajes a QQ a través del protocolo OneAPI.group
: enviar a través de un grupo de canales de envío de mensajes preconfigurado.custom
: envíe a través de un canal de envío personalizado preconfigurado.tencent_alarm
: enviada a través de las alarmas de monitoreo de Tencent Cloud, solo se admite el campo description
.none
: solo guarde en la base de datos, no presione.token
: si configura un token de inserción en segundo plano, este elemento es obligatorio. Esto también se puede configurar configurando el encabezado de Authorization
HTTP.url
: Opcional, si no se completa, el sistema generará automáticamente una URL para el mensaje y su contenido serán los detalles del mensaje.to
: Opcional, envíelo al usuario especificado. Si no lo completa, se lo enviará a usted mismo de forma predeterminada. Está limitado por el método de envío de mensajes específico y algunos métodos de envío no lo admiten.@all
: enviar a todos los usuarios.user1|user2|user3
: enviar a varios usuarios, separados por |
async
: Opcional, si se establece en true
, la inserción de mensajes se realizará de forma asincrónica en segundo plano y el resultado devuelto contiene el campo uuid
, que se puede usar para [Obtener estado de envío de mensajes] posterior (./docs/API.md#Get estado de envío del mensaje a través del UUID del mensaje).render_mode
: opcional,code
, el cuerpo del mensaje se anidará automáticamente en el bloque de código para su representación;raw
, no se realizará el análisis de Markdown;markdown
, que significa análisis de Markdown.POST
: los campos son consistentes con el método de solicitud GET
anterior.Content-Type
del encabezado HTTP debe establecerse en application/json
; de lo contrario, se procesará como formulario.token
en el modo de solicitud POST también se puede configurar mediante parámetros de consulta de URL.Nivel de soporte para varios canales:
tipo de canal | title | description | content | url | to | Soporte de rebajas |
---|---|---|---|---|---|---|
email | ✅ | ✅ | ✅ | ✅️ | ✅️ | |
test | ✅ | ✅ | ✅ | ✅️ | ✅️ | ✅ |
corp_app | ✅ | ✅ | ✅ | ✅️ | ✅ | ✅ |
corp | ✅ | ✅ | ✅️ | ✅️ | ✅ | |
lark | ✅ | ✅ | ✅ | ✅ | ||
lark_app | ✅ | ✅ | ️ | ✅ | ✅ | |
ding | ✅ | ✅ | ✅ | ✅️ | ✅ | ✅ |
bark | ✅ | ✅ | ✅ | ✅️ | ✅ | |
client | ✅ | ✅ | ||||
telegram | ✅ | ✅ | ✅ | |||
discord | ✅ | ✅ | ||||
tencent_alarm | ✅ |
Aviso:
description
y content
no pueden existir al mismo tiempo. Si solo necesita mensajes de texto, utilice description
. Si necesita enviar mensajes de Markdown, utilice content
.Ejemplo:
#! /bin/bash
MESSAGE_PUSHER_SERVER= " https://msgpusher.com "
MESSAGE_PUSHER_USERNAME= " test "
MESSAGE_PUSHER_TOKEN= " 666 "
function send_message {
# POST Form
curl -s -X POST " $MESSAGE_PUSHER_SERVER /push/ $MESSAGE_PUSHER_USERNAME "
-d " title= $1 &description= $2 &content= $3 &token= $MESSAGE_PUSHER_TOKEN "
> /dev/null
}
function send_message_with_json {
# POST JSON
curl -s -X POST " $MESSAGE_PUSHER_SERVER /push/ $MESSAGE_PUSHER_USERNAME "
-H ' Content-Type: application/json '
-d ' {"title":" ' " $1 " ' ","desp":" ' " $2 " ' ", "content":" ' " $3 " ' ", "token":" ' " $MESSAGE_PUSHER_TOKEN " ' "} '
> /dev/null
}
send_message ' title ' ' description ' ' content '
Otra versión:
MESSAGE_PUSHER_SERVER= " https://msgpusher.com "
MESSAGE_PUSHER_USERNAME= " test "
MESSAGE_PUSHER_TOKEN= " 666 "
MESSAGE_PUSHER_CHANNEL= " lark "
sendmsg () {
if [ -t 0 ] ; then
local param= " $* "
else
local param= $( < /dev/stdin )
fi
curl -s -o /dev/null --get --data-urlencode " content= ${param} " " $MESSAGE_PUSHER_SERVER /push/ $MESSAGE_PUSHER_USERNAME ?channel= $MESSAGE_PUSHER_CHANNEL &token= $MESSAGE_PUSHER_TOKEN "
}
Entonces puedes hacer algo como esto:
uname -ra | sendmsg
import requests
SERVER = "https://msgpusher.com"
USERNAME = "test"
TOKEN = "666"
def send_message ( title , description , content ):
# GET 方式
# res = requests.get(f"{SERVER}/push/{USERNAME}?title={title}"
# f"&description={description}&content={content}&token={TOKEN}")
# POST 方式
res = requests . post ( f" { SERVER } /push/ { USERNAME } " , json = {
"title" : title ,
"description" : description ,
"content" : content ,
"token" : TOKEN
})
res = res . json ()
if res [ "success" ]:
return None
else :
return res [ "message" ]
error = send_message ( "标题" , "描述" , "**Markdown 内容**" )
if error :
print ( error )
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
)
var serverAddress = "https://msgpusher.com"
var username = "test"
var token = "666"
type request struct {
Title string `json:"title"`
Description string `json:"description"`
Content string `json:"content"`
URL string `json:"url"`
Channel string `json:"channel"`
Token string `json:"token"`
}
type response struct {
Success bool `json:"success"`
Message string `json:"message"`
}
func SendMessage ( title string , description string , content string ) error {
req := request {
Title : title ,
Description : description ,
Content : content ,
Token : token ,
}
data , err := json . Marshal ( req )
if err != nil {
return err
}
resp , err := http . Post ( fmt . Sprintf ( "%s/push/%s" , serverAddress , username ),
"application/json" , bytes . NewBuffer ( data ))
if err != nil {
return err
}
var res response
err = json . NewDecoder ( resp . Body ). Decode ( & res )
if err != nil {
return err
}
if ! res . Success {
return errors . New ( res . Message )
}
return nil
}
func SendMessageWithForm ( title string , description string , content string ) error {
resp , err := http . PostForm ( fmt . Sprintf ( "%s/push/%s" , serverAddress , username ),
url. Values { "title" : { title }, "description" : { description }, "content" : { content }, "token" : { token }})
if err != nil {
return err
}
var res response
err = json . NewDecoder ( resp . Body ). Decode ( & res )
if err != nil {
return err
}
if ! res . Success {
return errors . New ( res . Message )
}
return nil
}
func main () {
//err := SendMessage("标题", "描述", "**Markdown 内容**")
err := SendMessageWithForm ( "标题" , "描述" , "**Markdown 内容**" )
if err != nil {
fmt . Println ( "推送失败:" + err . Error ())
} else {
fmt . Println ( "推送成功!" )
}
}
using Newtonsoft . Json ;
using RestSharp ;
namespace Demo
{
public class Program
{
public static void Main ( string [ ] args )
{
//推送消息
var sendMsg = MessagePusherTool . SendMessage ( "标题" , "描述" , "**Markdown 内容**" ) ;
if ( sendMsg . Success )
{
Console . WriteLine ( $ "推送成功!" ) ;
}
else
{
Console . WriteLine ( $ "推送失败: { sendMsg . Message } " ) ;
}
}
}
/// <summary>
/// 消息推送工具
///
/// <para>开源地址:https://github.com/songquanpeng/message-pusher</para>
/// <para>支持:Framework、Net3.1、Net5、Net6</para>
/// <para>引用包:</para>
/// <para>dotnet add package Newtonsoft.Json -v 13.0.2</para>
/// <para>dotnet add package RestSharp -v 108.0.3</para>
/// </summary>
public class MessagePusherTool
{
/// <summary>
/// ServerAddress
/// </summary>
public const string ServerAddress = "https://msgpusher.com" ;
/// <summary>
/// UserName
/// </summary>
public const string UserName = "test" ;
/// <summary>
/// Token
/// </summary>
public const string Token = "666" ;
/// <summary>
/// SendMessage
/// </summary>
/// <param name="title">title</param>
/// <param name="description">description</param>
/// <param name="content">content</param>
public static Response SendMessage ( string title , string description , string content )
{
var requestData = new Request ( )
{
Title = title ,
Description = description ,
Content = content ,
Token = Token ,
} ;
var url = $ " { ServerAddress } " ;
var client = new RestClient ( url ) ;
var request = new RestRequest ( $ "push/ { UserName } " , Method . Post ) ;
request . AddJsonBody ( requestData ) ;
var response = client . Execute ( request ) ;
var responseData = response . Content ;
var responseJson = JsonConvert . DeserializeObject < Response > ( responseData ) ;
return responseJson ;
}
/// <summary>
/// Request
/// </summary>
public class Request
{
/// <summary>
/// Title
/// </summary>
[ JsonProperty ( PropertyName = "title" ) ]
public string Title { get ; set ; }
/// <summary>
/// Description
/// </summary>
[ JsonProperty ( PropertyName = "description" ) ]
public string Description { get ; set ; }
/// <summary>
/// Content
/// </summary>
[ JsonProperty ( PropertyName = "content" ) ]
public string Content { get ; set ; }
/// <summary>
/// URL
/// </summary>
[ JsonProperty ( PropertyName = "url" ) ]
public string URL { get ; set ; }
/// <summary>
/// Channel
/// </summary>
[ JsonProperty ( PropertyName = "channel" ) ]
public string Channel { get ; set ; }
/// <summary>
/// Token
/// </summary>
[ JsonProperty ( PropertyName = "token" ) ]
public string Token { get ; set ; }
}
/// <summary>
/// Response
/// </summary>
public class Response
{
/// <summary>
/// Success
/// </summary>
[ JsonProperty ( PropertyName = "success" ) ]
public bool Success { get ; set ; }
/// <summary>
/// Message
/// </summary>
[ JsonProperty ( PropertyName = "message" ) ]
public string Message { get ; set ; }
}
}
}
const axios = require ( 'axios' ) ;
const querystring = require ( 'querystring' ) ;
const MESSAGE_PUSHER_SERVER = 'https://msgpusher.com'
const MESSAGE_PUSHER_USERNAME = 'test'
const MESSAGE_PUSHER_TOKEN = '666'
async function send_message ( title , description , content ) {
try {
const postData = querystring . stringify ( {
title : title ,
desp : description ,
content : content ,
token : MESSAGE_PUSHER_TOKEN ,
} )
const response = await axios . post ( ` ${ MESSAGE_PUSHER_SERVER } /push/ ${ MESSAGE_PUSHER_USERNAME } ` , postData , {
headers : {
'Content-Type' : 'application/x-www-form-urlencoded' ,
} ,
} )
if ( response . data . success ) {
return response . data
}
} catch ( error ) {
if ( error . response ) {
return error . response . data
} else {
throw error
}
}
}
send_message ( '标题' , '描述' , '**Markdown 内容**' )
. then ( ( response ) => {
if ( response . success ) {
console . log ( '推送成功:' , response )
} else {
console . log ( '推送失败:' , response )
}
} , ( error ) => {
console . log ( error . message ) ;
} )
Los RP pueden agregar ejemplos en más idiomas.
Aquí se utiliza SQLite como ejemplo. Modifique otras bases de datos usted mismo. Le pedí a ChatGPT que lo tradujera a la versión SQL correspondiente; consulte la carpeta bin
como referencia.
v0.3
a v0.4
v0.4
, inicie el programa y el programa migrará automáticamente la estructura de la tabla de la base de datos../bin/migrate_v3_to_v4.py
para migrar datos. Tenga en cuenta que antes de la ejecución, asegúrese de que el orden de los campos en la tabla de users
de la base de datos sea coherente con el del script; de lo contrario, se producirá confusión en los datos.
v0.3
se basan en Node.js. Puede cambiar a nodejs
para verla. Esta versión ya no tiene actualizaciones funcionales.v0.3
y versiones posteriores se desarrollan en base a Gin Template v0.2.1
.pattern web/build: no matching files found
.