Erstellen Sie Ihren eigenen Nachrichten-Push-Dienst, unterstützen Sie mehrere Nachrichten-Push-Methoden, unterstützen Sie Markdown, nur eine einzige ausführbare Datei, sofort einsatzbereit
Programm-Download·Bereitstellungs-Tutorial·Nutzungs-Tutorial·Feedback·Online-Demonstration
Hinweis : Die offizielle Bereitstellungsseite https://msgpusher.com ist jetzt online und die Registrierung ist derzeit geöffnet. Wenn Sie positives Feedback erhalten, können Sie in Zukunft einen Wechsel zu einem Server mit geringerer Latenz in Betracht ziehen.
Warnung : Ein Upgrade von
v0.3
aufv0.4
erfordert eine manuelle Migration der Datenbank. Weitere Informationen finden Sie unter Migration der Datenbank.
Bereitstellung: 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
Wenn es nicht abgerufen werden kann, ersetzen Sie bitte justsong/message-pusher
durch ghcr.io/songquanpeng/message-pusher
.
Update: docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR
Die offene Portnummer ist 3000. Verwenden Sie dann Nginx, um den Domänennamen, die umgekehrte Generierung und das SSL-Zertifikat zu konfigurieren. Weitere Informationen finden Sie im ausführlichen Bereitstellungs-Tutorial.
Die Daten werden im Verzeichnis /home/ubuntu/data/message-pusher
des Hostcomputers gespeichert (es gibt nur eine SQLite-Datenbankdatei. Bitte stellen Sie sicher, dass das Verzeichnis vorhanden ist und über Schreibberechtigung verfügt, oder ändern Sie es in ein geeignetes Verzeichnis). .
Referenzkonfiguration von 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;
}
}
Verwenden Sie dann den Certbot von Let's Encrypt, um HTTPS zu konfigurieren:
# 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
und das Passwort ist 123456
.Wenn der Dienst über einen längeren Zeitraum ausgeführt werden muss, reicht es nicht aus, ihn einfach zu starten. Detailliertes Bereitstellungs-Tutorial.
Wenn Sie die WebSocket-Client-Push-Funktion verwenden müssen, müssen proxy_read_timeout
und proxy_send_timeout
in der Nginx-Konfigurationsdatei auf mehr als 1 Minute eingestellt werden.
Empfohlene Einstellungen:
proxy_read_timeout 300s;
proxy_send_timeout 300s;
Das System selbst muss lediglich eine ausführbare Datei herunterladen, um sie verwenden zu können, ohne weitere Abhängigkeiten.
Sie können es konfigurieren, indem Sie Umgebungsvariablen oder Befehlszeilenparameter festlegen.
Melden Sie sich nach dem Systemstart mit dem root
Benutzer am System an und nehmen Sie weitere Konfigurationen vor. Das Standardkennwort lautet 123456
.
REDIS_CONN_STRING
: Nach der Einstellung wird Redis als Speicher für die Anforderungshäufigkeitsbegrenzung verwendet, anstatt Speicherspeicher zu verwenden.REDIS_CONN_STRING=redis://default:redispw@localhost:49153
SESSION_SECRET
: Nach der Einstellung wird ein fester Sitzungsschlüssel verwendet, sodass das Cookie des angemeldeten Benutzers auch nach einem Neustart des Systems weiterhin gültig ist.SESSION_SECRET=random_string
SQL_DSN
: Nach der Einstellung wird die angegebene Datenbank anstelle von SQLite verwendet.SQL_DSN=root:123456@tcp(localhost:3306)/message-pusher
Hinweis: Bei der Bereitstellung mit Docker verwenden Sie bitte -e key=value
, um Umgebungsvariablen festzulegen.
Beispiel: docker run -e SESSION_SECRET=random_string ...
--port <port_number>
: Geben Sie die Portnummer an, die der Server überwacht. Der Standardwert ist 3000
.--port 3000
--log-dir <log_dir>
: Geben Sie den Protokollordner an. Wenn nicht festgelegt, wird das Protokoll nicht gespeichert.--log-dir ./logs
--version
: Gibt die Systemversionsnummer aus und beendet den Vorgang.允许新用户注册
.更新用户信息
um den Standardbenutzernamen und das Standardkennwort zu ändern.绑定邮箱地址
um E-Mails zu binden und das Pushen von E-Mail-Nachrichten zu ermöglichen.默认推送方式
fest. Die Standardeinstellung ist Push per E-Mail.推送token
für die Push-API-Aufrufauthentifizierung fest. Lassen Sie es leer, wenn es nicht erforderlich ist.测试
, um zu testen, ob die Konfiguration erfolgreich ist.https://<domain>/push/<username>
<domain>
und <username>
durch echte Werte, zum Beispiel: https://push.mydomain.cn/push/admin
GET
Anfragemethode: https://<domain>/push/<username>?title=<标题>&description=<描述>&content=<Markdown 文本>&channel=<推送方式>&token=<推送token>
title
: Optional, begrenzt durch die spezifische Nachrichten-Push-Methode, kann ignoriert werden.description
: erforderlich, kann durch desp
ersetzt werden.content
: Optional, begrenzt durch die spezifische Nachrichten-Push-Methode. Die Unterstützung der Markdown-Syntax ist unterschiedlich.channel
: Optional, wenn nicht ausgefüllt, verwendet das System den Standard-Push-Kanal, den Sie im Hintergrund festgelegt haben. Beachten Sie, dass hier der Name des Nachrichtenkanals eingetragen wird, nicht der Typ. Optionale Push-Kanaltypen sind:email
: Push durch Senden einer E-Mail (verwenden Sie das title
oder description
, um den E-Mail-Betreff festzulegen, verwenden Sie content
, um den Text festzulegen, und unterstützen Sie die vollständige Markdown-Syntax).test
: Push durch das WeChat-Testkonto (verwenden Sie das description
, um den Inhalt der Vorlagennachricht festzulegen, Markdown wird nicht unterstützt).corp_app
: Übertragen Sie das WeChat-Anwendungskonto des Unternehmens (nur bei Verwendung der WeChat-App des Unternehmens. Wenn das content
festgelegt ist, werden title
und description
ignoriert. Dies ist normal, wenn das WeChat-Plug-in des Unternehmens in WeChat verwendet wird.)lark_app
: Setzen Sie Feishus selbst erstellte Anwendung durch.corp
: Wird durch den WeChat-Gruppenroboter des Unternehmens gepusht (durch Festlegen des content
werden Markdown-Nachrichten gerendert, wobei eine Teilmenge von Markdown unterstützt wird; durch Festlegen description
werden normale Textnachrichten gerendert).lark
: Push über Feishuqun-Roboter (Hinweise sind die gleichen wie oben).ding
: Push über den DingTalk-Gruppenroboter (Hinweise sind die gleichen wie oben).bark
: Push durch Bark (unterstützt title
und description
).client
: Push über WebSocket-Client (unterstützt title
und description
).telegram
: Push per Telegram-Roboter (wählen Sie eines der description
oder content
, unterstützt eine Teilmenge von Markdown).discord
: Push-Through-Discord-Gruppen-Bot (Notizen sind die gleichen wie oben).one_api
: Push-Nachrichten über das OneAPI-Protokoll an QQ senden.group
: Push durch eine vorkonfigurierte Nachrichten-Push-Kanalgruppe.custom
: Push über einen vorkonfigurierten benutzerdefinierten Push-Kanal.tencent_alarm
: Wird durch Tencent Cloud-Überwachungsalarme übertragen, nur das description
wird unterstützt.none
: Nur in der Datenbank speichern, nicht pushen.token
: Wenn Sie im Hintergrund ein Push-Token festlegen, ist dieses Element erforderlich. Dies kann auch durch Festlegen des HTTP- Authorization
festgelegt werden.url
: Optional, wenn nicht ausgefüllt, generiert das System automatisch eine URL für die Nachricht und ihr Inhalt sind die Nachrichtendetails.to
: Optional, an den angegebenen Benutzer senden. Wird standardmäßig an Sie selbst gesendet. Dies ist durch die spezifische Nachrichten-Push-Methode eingeschränkt und wird von einigen Push-Methoden nicht unterstützt.@all
: Push an alle Benutzer.user1|user2|user3
: Push an mehrere Benutzer, getrennt durch |
.async
: Optional, wenn auf true
gesetzt, wird der Nachrichten-Push asynchron im Hintergrund ausgeführt und das Rückgabeergebnis enthält das uuid
-Feld, das für nachfolgende [Status des Nachrichtenversands abrufen] (./docs/API.md#Get) verwendet werden kann Nachrichtensendestatus über Nachrichten-UUID).render_mode
: optional,code
wird der Nachrichtentext zum Rendern automatisch im Codeblock verschachtelt.raw
wird kein Markdown-Parsing durchgeführt;markdown
, was Markdown-Analyse bedeutet.POST
Anfragemethode: Die Felder stimmen mit der oben genannten GET
Anfragemethode überein.Content-Type
auf application/json
gesetzt werden, andernfalls wird er als Formular verarbeitet.token
Feld im POST-Anfragemodus kann auch über URL-Abfrageparameter festgelegt werden.Unterstützungsgrad für verschiedene Kanäle:
Kanaltyp | title | description | content | url | to | Markdown-Unterstützung |
---|---|---|---|---|---|---|
email | ✅ | ✅ | ✅ | ✅️ | ✅️ | |
test | ✅ | ✅ | ✅ | ✅️ | ✅️ | ✅ |
corp_app | ✅ | ✅ | ✅ | ✅️ | ✅ | ✅ |
corp | ✅ | ✅ | ✅️ | ✅️ | ✅ | |
lark | ✅ | ✅ | ✅ | ✅ | ||
lark_app | ✅ | ✅ | ️ | ✅ | ✅ | |
ding | ✅ | ✅ | ✅ | ✅️ | ✅ | ✅ |
bark | ✅ | ✅ | ✅ | ✅️ | ✅ | |
client | ✅ | ✅ | ||||
telegram | ✅ | ✅ | ✅ | |||
discord | ✅ | ✅ | ||||
tencent_alarm | ✅ |
Beachten:
description
und content
nicht gleichzeitig vorhanden sein. Wenn Sie nur Textnachrichten benötigen, verwenden Sie bitte description
. Wenn Sie Markdown-Nachrichten senden müssen, verwenden Sie bitte content
Inhaltsfeld.Beispiel:
#! /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 '
Eine andere Version:
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 "
}
Dann können Sie so etwas tun:
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 ) ;
} )
PRs können gerne Beispiele in weiteren Sprachen hinzufügen.
Als Beispiel dient hier SQLite. Bitte modifizieren Sie selbst andere Datenbanken. Ich habe ChatGPT gebeten, es in die entsprechende SQL-Version zu übersetzen. Weitere Informationen finden Sie im bin
Ordner.
v0.3
auf v0.4
migrierenv0.4
herunter, starten Sie das Programm und das Programm migriert automatisch die Datenbanktabellenstruktur../bin/migrate_v3_to_v4.py
aus, um Daten zu migrieren. Beachten Sie, dass Sie vor der Ausführung sicherstellen müssen, dass die Reihenfolge der Felder in der users
in der Datenbank mit der im Skript übereinstimmt, da es sonst zu Datenverwechslungen kommt.
v0.3
basieren auf Node.js. Sie können zum Knoten nodejs
wechseln, um es anzuzeigen. Diese Version verfügt nicht mehr über funktionale Updates.v0.3
und nachfolgende Versionen werden basierend auf Gin Template v0.2.1
entwickelt.pattern web/build: no matching files found
auf.