├── .env.example ├── .gitignore ├── LICENSE ├── README.md ├── c ├── main └── main.c ├── csharp ├── Program.cs └── csharp.csproj ├── dart ├── .dart_tool │ ├── extension_discovery │ │ ├── README.md │ │ └── vs_code.json │ ├── package_config.json │ ├── package_config_subset │ └── version ├── main.dart ├── pubspec.lock └── pubspec.yaml ├── golang ├── go.mod ├── main.go └── serverchan ├── java ├── Main.class └── Main.java ├── nodejs ├── package-lock.json ├── package.json ├── send.js └── yarn.lock ├── php └── send.php ├── python └── send.py ├── rust ├── Cargo.lock ├── Cargo.toml └── src │ └── main.rs ├── shell └── send.sh └── swift └── main.swift /.env.example: -------------------------------------------------------------------------------- 1 | SENDKEY= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules 3 | rust/target 4 | csharp/bin 5 | csharp/obj -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Easy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Server酱多语言调用实例 2 | 3 | > 2024-10-01 更新,全部实例均已兼容[Server酱³](https://sc3.ft07.com),[多语言SDK](https://github.com/easychen/serverchan-sdk)也已经上线 4 | 5 | 借助于 GPT 我们编写了多种语言的Server酱调用实例。包括 6 | 7 | - C 8 | - C# 9 | - Dart 10 | - Go 11 | - Java 12 | - NodeJS 13 | - PHP 14 | - Python 15 | - Rust 16 | - Shell 17 | - Swift 18 | 19 | ## 测试方式 20 | 21 | 将`.env.example`改名为`.env`,填入sendkey,即可测试。 22 | 23 | > 注意:Dart中读取.env文件失败,可以手工在main.dart中手工写入sendkey测试。 24 | 25 | ### 运行命令 26 | 27 | - php send.php 28 | - node send.js 29 | - python send.py 30 | - java Main.java 31 | - go run main.go 32 | - cargo run 33 | - bash send.sh 34 | - swift main.swift 35 | - dart run main.dart 36 | - gcc main.c -o main -lcurl && ./main -------------------------------------------------------------------------------- /c/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/serverchan-demo/481eccec5c3a6da71d6e744207a145d31a92b5a5/c/main -------------------------------------------------------------------------------- /c/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAX_BUFFER_SIZE 1024 7 | 8 | // gcc -o main main.c -lcurl 9 | 10 | typedef struct { 11 | char* text; 12 | char* desp; 13 | char* key; 14 | } SCData; 15 | 16 | size_t write_callback(void* contents, size_t size, size_t nmemb, char* buffer) { 17 | size_t total_size = size * nmemb; 18 | strncat(buffer, contents, total_size); 19 | return total_size; 20 | } 21 | 22 | void sc_send(SCData* data) { 23 | CURL* curl; 24 | CURLcode res; 25 | char url[MAX_BUFFER_SIZE]; 26 | char post_data[MAX_BUFFER_SIZE]; 27 | char response[MAX_BUFFER_SIZE]; 28 | 29 | curl_global_init(CURL_GLOBAL_DEFAULT); 30 | curl = curl_easy_init(); 31 | if (curl) { 32 | // 判断 sendkey 是否以 "sctp" 开头,并提取后续数字 33 | if (strncmp(data->key, "sctp", 4) == 0) { 34 | int num; 35 | if (sscanf(data->key, "sctp%dt", &num) == 1) { 36 | snprintf(url, MAX_BUFFER_SIZE, "https://%d.push.ft07.com/send/%s.send", num, data->key); 37 | } else { 38 | fprintf(stderr, "Invalid sendkey format for sctp\n"); 39 | curl_easy_cleanup(curl); 40 | curl_global_cleanup(); 41 | return; 42 | } 43 | } else { 44 | snprintf(url, MAX_BUFFER_SIZE, "https://sctapi.ftqq.com/%s.send", data->key); 45 | } 46 | 47 | snprintf(post_data, MAX_BUFFER_SIZE, "text=%s&desp=%s", data->text, data->desp); 48 | 49 | curl_easy_setopt(curl, CURLOPT_URL, url); 50 | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data); 51 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); 52 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, response); 53 | 54 | res = curl_easy_perform(curl); 55 | if (res != CURLE_OK) { 56 | fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); 57 | } 58 | 59 | curl_easy_cleanup(curl); 60 | } 61 | 62 | curl_global_cleanup(); 63 | 64 | printf("%s\n", response); 65 | } 66 | 67 | int main() { 68 | char* dotenv_path = "../.env"; 69 | char* sendkey = NULL; 70 | FILE* dotenv_file = fopen(dotenv_path, "r"); 71 | if (dotenv_file) { 72 | char line[MAX_BUFFER_SIZE]; 73 | while (fgets(line, sizeof(line), dotenv_file)) { 74 | char* key = strtok(line, "="); 75 | char* value = strtok(NULL, "="); 76 | if (strcmp(key, "SENDKEY") == 0) { 77 | sendkey = strdup(value); 78 | break; 79 | } 80 | } 81 | fclose(dotenv_file); 82 | } 83 | 84 | if (sendkey) { 85 | SCData data; 86 | data.text = "主人服务器宕机了 via c"; 87 | data.desp = "第一行\n\n第二行"; 88 | data.key = sendkey; 89 | 90 | sc_send(&data); 91 | 92 | free(sendkey); 93 | } 94 | 95 | return 0; 96 | } -------------------------------------------------------------------------------- /csharp/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net.Http; 4 | using System.Text; 5 | using System.Text.RegularExpressions; 6 | using System.Threading.Tasks; 7 | 8 | class Program 9 | { 10 | static async Task Main(string[] args) 11 | { 12 | string data = File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "../.env")); 13 | var key = data.Split('=')[1].Trim(); 14 | 15 | var ret = await ScSend("主人服务器宕机了", "第一行\n\n第二行", key); 16 | Console.WriteLine(ret); 17 | } 18 | 19 | static async Task ScSend(string text, string desp = "", string key = "[SENDKEY]") 20 | { 21 | var postData = $"text={Uri.EscapeDataString(text)}&desp={Uri.EscapeDataString(desp)}"; 22 | // 判断 sendkey 是否以 "sctp" 开头并提取数字部分 23 | if (key.StartsWith("sctp")) 24 | { 25 | var match = Regex.Match(key, @"^sctp(\d+)t"); 26 | if (match.Success) 27 | { 28 | var num = match.Groups[1].Value; 29 | url = $"https://{num}.push.ft07.com/send/{key}.send"; 30 | } 31 | else 32 | { 33 | throw new ArgumentException("Invalid key format for sctp."); 34 | } 35 | } 36 | else 37 | { 38 | url = $"https://sctapi.ftqq.com/{key}.send"; 39 | } 40 | 41 | var httpClient = new HttpClient(); 42 | var request = new HttpRequestMessage(HttpMethod.Post, url); 43 | request.Content = new StringContent(postData, Encoding.UTF8, "application/x-www-form-urlencoded"); 44 | 45 | var response = await httpClient.SendAsync(request); 46 | var responseStream = await response.Content.ReadAsStreamAsync(); 47 | var reader = new StreamReader(responseStream); 48 | 49 | return await reader.ReadToEndAsync(); 50 | } 51 | } -------------------------------------------------------------------------------- /csharp/csharp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /dart/.dart_tool/extension_discovery/README.md: -------------------------------------------------------------------------------- 1 | Extension Discovery Cache 2 | ========================= 3 | 4 | This folder is used by `package:extension_discovery` to cache lists of 5 | packages that contains extensions for other packages. 6 | 7 | DO NOT USE THIS FOLDER 8 | ---------------------- 9 | 10 | * Do not read (or rely) the contents of this folder. 11 | * Do write to this folder. 12 | 13 | If you're interested in the lists of extensions stored in this folder use the 14 | API offered by package `extension_discovery` to get this information. 15 | 16 | If this package doesn't work for your use-case, then don't try to read the 17 | contents of this folder. It may change, and will not remain stable. 18 | 19 | Use package `extension_discovery` 20 | --------------------------------- 21 | 22 | If you want to access information from this folder. 23 | 24 | Feel free to delete this folder 25 | ------------------------------- 26 | 27 | Files in this folder act as a cache, and the cache is discarded if the files 28 | are older than the modification time of `.dart_tool/package_config.json`. 29 | 30 | Hence, it should never be necessary to clear this cache manually, if you find a 31 | need to do please file a bug. 32 | -------------------------------------------------------------------------------- /dart/.dart_tool/extension_discovery/vs_code.json: -------------------------------------------------------------------------------- 1 | {"version":2,"entries":[{"package":"serverchan","rootUri":"../","packageUri":"lib/"}]} -------------------------------------------------------------------------------- /dart/.dart_tool/package_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "configVersion": 2, 3 | "packages": [ 4 | { 5 | "name": "async", 6 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/async-2.11.0", 7 | "packageUri": "lib/", 8 | "languageVersion": "2.18" 9 | }, 10 | { 11 | "name": "collection", 12 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/collection-1.17.2", 13 | "packageUri": "lib/", 14 | "languageVersion": "2.18" 15 | }, 16 | { 17 | "name": "dart_dotenv", 18 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/dart_dotenv-1.0.1", 19 | "packageUri": "lib/", 20 | "languageVersion": "2.12" 21 | }, 22 | { 23 | "name": "http", 24 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/http-0.13.5", 25 | "packageUri": "lib/", 26 | "languageVersion": "2.14" 27 | }, 28 | { 29 | "name": "http_parser", 30 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/http_parser-4.0.2", 31 | "packageUri": "lib/", 32 | "languageVersion": "2.12" 33 | }, 34 | { 35 | "name": "meta", 36 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/meta-1.9.1", 37 | "packageUri": "lib/", 38 | "languageVersion": "2.12" 39 | }, 40 | { 41 | "name": "path", 42 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/path-1.8.3", 43 | "packageUri": "lib/", 44 | "languageVersion": "2.12" 45 | }, 46 | { 47 | "name": "source_span", 48 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/source_span-1.10.0", 49 | "packageUri": "lib/", 50 | "languageVersion": "2.18" 51 | }, 52 | { 53 | "name": "string_scanner", 54 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/string_scanner-1.2.0", 55 | "packageUri": "lib/", 56 | "languageVersion": "2.18" 57 | }, 58 | { 59 | "name": "term_glyph", 60 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/term_glyph-1.2.1", 61 | "packageUri": "lib/", 62 | "languageVersion": "2.12" 63 | }, 64 | { 65 | "name": "typed_data", 66 | "rootUri": "file:///Users/easy/.pub-cache/hosted/pub.dev/typed_data-1.3.2", 67 | "packageUri": "lib/", 68 | "languageVersion": "2.17" 69 | }, 70 | { 71 | "name": "serverchan", 72 | "rootUri": "../", 73 | "packageUri": "lib/", 74 | "languageVersion": "2.12" 75 | } 76 | ], 77 | "generated": "2024-09-30T16:28:48.375496Z", 78 | "generator": "pub", 79 | "generatorVersion": "3.4.4", 80 | "pubCache": "file:///Users/easy/.pub-cache" 81 | } 82 | -------------------------------------------------------------------------------- /dart/.dart_tool/package_config_subset: -------------------------------------------------------------------------------- 1 | args 2 | 2.18 3 | file:///Users/easy/.pub-cache/hosted/pub.dev/args-2.4.1/ 4 | file:///Users/easy/.pub-cache/hosted/pub.dev/args-2.4.1/lib/ 5 | async 6 | 2.18 7 | file:///Users/easy/.pub-cache/hosted/pub.dev/async-2.11.0/ 8 | file:///Users/easy/.pub-cache/hosted/pub.dev/async-2.11.0/lib/ 9 | collection 10 | 2.18 11 | file:///Users/easy/.pub-cache/hosted/pub.dev/collection-1.17.2/ 12 | file:///Users/easy/.pub-cache/hosted/pub.dev/collection-1.17.2/lib/ 13 | dotenv 14 | 2.12 15 | file:///Users/easy/.pub-cache/hosted/pub.dev/dotenv-3.0.0/ 16 | file:///Users/easy/.pub-cache/hosted/pub.dev/dotenv-3.0.0/lib/ 17 | http 18 | 2.14 19 | file:///Users/easy/.pub-cache/hosted/pub.dev/http-0.13.5/ 20 | file:///Users/easy/.pub-cache/hosted/pub.dev/http-0.13.5/lib/ 21 | http_parser 22 | 2.12 23 | file:///Users/easy/.pub-cache/hosted/pub.dev/http_parser-4.0.2/ 24 | file:///Users/easy/.pub-cache/hosted/pub.dev/http_parser-4.0.2/lib/ 25 | meta 26 | 2.12 27 | file:///Users/easy/.pub-cache/hosted/pub.dev/meta-1.9.1/ 28 | file:///Users/easy/.pub-cache/hosted/pub.dev/meta-1.9.1/lib/ 29 | path 30 | 2.12 31 | file:///Users/easy/.pub-cache/hosted/pub.dev/path-1.8.3/ 32 | file:///Users/easy/.pub-cache/hosted/pub.dev/path-1.8.3/lib/ 33 | source_span 34 | 2.18 35 | file:///Users/easy/.pub-cache/hosted/pub.dev/source_span-1.10.0/ 36 | file:///Users/easy/.pub-cache/hosted/pub.dev/source_span-1.10.0/lib/ 37 | string_scanner 38 | 2.18 39 | file:///Users/easy/.pub-cache/hosted/pub.dev/string_scanner-1.2.0/ 40 | file:///Users/easy/.pub-cache/hosted/pub.dev/string_scanner-1.2.0/lib/ 41 | term_glyph 42 | 2.12 43 | file:///Users/easy/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/ 44 | file:///Users/easy/.pub-cache/hosted/pub.dev/term_glyph-1.2.1/lib/ 45 | typed_data 46 | 2.17 47 | file:///Users/easy/.pub-cache/hosted/pub.dev/typed_data-1.3.2/ 48 | file:///Users/easy/.pub-cache/hosted/pub.dev/typed_data-1.3.2/lib/ 49 | serverchan 50 | 2.12 51 | file:///Users/easy/Code/gitcode/serverchan-functions/dart/ 52 | file:///Users/easy/Code/gitcode/serverchan-functions/dart/lib/ 53 | 2 54 | -------------------------------------------------------------------------------- /dart/.dart_tool/version: -------------------------------------------------------------------------------- 1 | 3.7.9 -------------------------------------------------------------------------------- /dart/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:http/http.dart' as http; 2 | import 'package:dart_dotenv/dart_dotenv.dart'; 3 | 4 | void main() async { 5 | final dotEnv = DotEnv(filePath: '../.env'); 6 | // 打印 dotEnv 内容 7 | print(dotEnv); 8 | final key = dotEnv.get('SENDKEY') ?? ''; 9 | 10 | if (key != null) { 11 | final ret = await scSend('主人服务器宕机了 via dart', '第一行\n\n第二行', key); 12 | print(ret); 13 | } else { 14 | print('SENDKEY is not found in .env file'); 15 | } 16 | } 17 | 18 | Future scSend(String text, [String desp = '', String? key]) async { 19 | key = key ?? '[SENDKEY]'; 20 | String url; 21 | if (key.startsWith('sctp')) { 22 | final regExp = RegExp(r'sctp(\d+)t'); 23 | final match = regExp.firstMatch(key); 24 | if (match != null) { 25 | final num = match.group(1); // 提取数字部分 26 | url = 'https://$num.push.ft07.com/send/$key.send'; 27 | } else { 28 | throw ArgumentError('Invalid key format'); 29 | } 30 | } else { 31 | url = 'https://sctapi.ftqq.com/$key.send'; 32 | } 33 | 34 | final request = http.MultipartRequest('POST', Uri.parse(url)); 35 | request.fields['text'] = text; 36 | request.fields['desp'] = desp; 37 | 38 | final response = await request.send(); 39 | final responseBody = await response.stream.bytesToString(); 40 | 41 | return responseBody; 42 | } 43 | -------------------------------------------------------------------------------- /dart/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" 9 | url: "https://pub.dev" 10 | source: hosted 11 | version: "2.11.0" 12 | collection: 13 | dependency: transitive 14 | description: 15 | name: collection 16 | sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 17 | url: "https://pub.dev" 18 | source: hosted 19 | version: "1.17.2" 20 | dart_dotenv: 21 | dependency: "direct main" 22 | description: 23 | name: dart_dotenv 24 | sha256: "299c2b0358e4d1d50f0468c00f17ab206c770eb6380d1e3c1b9098b6d2ba7dbf" 25 | url: "https://pub.dev" 26 | source: hosted 27 | version: "1.0.1" 28 | http: 29 | dependency: "direct main" 30 | description: 31 | name: http 32 | sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" 33 | url: "https://pub.dev" 34 | source: hosted 35 | version: "0.13.5" 36 | http_parser: 37 | dependency: transitive 38 | description: 39 | name: http_parser 40 | sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" 41 | url: "https://pub.dev" 42 | source: hosted 43 | version: "4.0.2" 44 | meta: 45 | dependency: transitive 46 | description: 47 | name: meta 48 | sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" 49 | url: "https://pub.dev" 50 | source: hosted 51 | version: "1.9.1" 52 | path: 53 | dependency: transitive 54 | description: 55 | name: path 56 | sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" 57 | url: "https://pub.dev" 58 | source: hosted 59 | version: "1.8.3" 60 | source_span: 61 | dependency: transitive 62 | description: 63 | name: source_span 64 | sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" 65 | url: "https://pub.dev" 66 | source: hosted 67 | version: "1.10.0" 68 | string_scanner: 69 | dependency: transitive 70 | description: 71 | name: string_scanner 72 | sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" 73 | url: "https://pub.dev" 74 | source: hosted 75 | version: "1.2.0" 76 | term_glyph: 77 | dependency: transitive 78 | description: 79 | name: term_glyph 80 | sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 81 | url: "https://pub.dev" 82 | source: hosted 83 | version: "1.2.1" 84 | typed_data: 85 | dependency: transitive 86 | description: 87 | name: typed_data 88 | sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c 89 | url: "https://pub.dev" 90 | source: hosted 91 | version: "1.3.2" 92 | sdks: 93 | dart: ">=2.18.0 <4.0.0" 94 | -------------------------------------------------------------------------------- /dart/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: serverchan 2 | environment: 3 | sdk: '^2.12.0' 4 | dependencies: 5 | http: ^0.13.3 6 | dart_dotenv: ^1.0.1 7 | -------------------------------------------------------------------------------- /golang/go.mod: -------------------------------------------------------------------------------- 1 | module serverchan 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /golang/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net/http" 7 | "net/url" 8 | "regexp" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | data, err := ioutil.ReadFile("../.env") 14 | if err != nil { 15 | fmt.Println(err) 16 | return 17 | } 18 | 19 | env := string(data) 20 | m, err := parseEnv(env) 21 | if err != nil { 22 | fmt.Println(err) 23 | return 24 | } 25 | 26 | key := m["SENDKEY"] 27 | 28 | ret := scSend("主人服务器宕机了 via go", "第一行\n\n第二行", key) 29 | fmt.Println(ret) 30 | } 31 | 32 | func parseEnv(env string) (map[string]string, error) { 33 | m := make(map[string]string) 34 | lines := strings.Split(env, "\n") 35 | for _, line := range lines { 36 | if line == "" || strings.HasPrefix(line, "#") { 37 | continue 38 | } 39 | parts := strings.Split(line, "=") 40 | if len(parts) != 2 { 41 | return nil, fmt.Errorf("Invalid .env format") 42 | } 43 | key := strings.TrimSpace(parts[0]) 44 | value := strings.TrimSpace(parts[1]) 45 | m[key] = value 46 | } 47 | return m, nil 48 | } 49 | 50 | func scSend(text string, desp string, key string) string { 51 | data := url.Values{} 52 | data.Set("text", text) 53 | data.Set("desp", desp) 54 | 55 | // 根据 sendkey 是否以 "sctp" 开头决定 API 的 URL 56 | var apiUrl string 57 | if strings.HasPrefix(key, "sctp") { 58 | // 使用正则表达式提取数字部分 59 | re := regexp.MustCompile(`sctp(\d+)t`) 60 | matches := re.FindStringSubmatch(key) 61 | if len(matches) > 1 { 62 | num := matches[1] 63 | apiUrl = fmt.Sprintf("https://%s.push.ft07.com/send/%s.send", num, key) 64 | } else { 65 | return "Invalid sendkey format for sctp" 66 | } 67 | } else { 68 | apiUrl = fmt.Sprintf("https://sctapi.ftqq.com/%s.send", key) 69 | } 70 | 71 | client := &http.Client{} 72 | req, err := http.NewRequest("POST", apiUrl, strings.NewReader(data.Encode())) 73 | if err != nil { 74 | return err.Error() 75 | } 76 | 77 | req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 78 | 79 | resp, err := client.Do(req) 80 | if err != nil { 81 | return err.Error() 82 | } 83 | defer resp.Body.Close() 84 | 85 | body, err := ioutil.ReadAll(resp.Body) 86 | if err != nil { 87 | return err.Error() 88 | } 89 | 90 | return string(body) 91 | } 92 | -------------------------------------------------------------------------------- /golang/serverchan: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/serverchan-demo/481eccec5c3a6da71d6e744207a145d31a92b5a5/golang/serverchan -------------------------------------------------------------------------------- /java/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/serverchan-demo/481eccec5c3a6da71d6e744207a145d31a92b5a5/java/Main.class -------------------------------------------------------------------------------- /java/Main.java: -------------------------------------------------------------------------------- 1 | import java.io.FileInputStream; 2 | import java.io.IOException; 3 | import java.io.BufferedReader; 4 | import java.io.DataOutputStream; 5 | import java.io.InputStreamReader; 6 | import java.net.HttpURLConnection; 7 | import java.net.URL; 8 | import java.net.URLEncoder; 9 | import java.util.Properties; 10 | import java.util.regex.*; 11 | 12 | public class Main { 13 | 14 | public static void main(String[] args) { 15 | Properties data = parseIniFile("../.env"); 16 | String key = data.getProperty("SENDKEY"); 17 | 18 | String ret = scSend("主人服务器宕机了 via java", "第一行\n\n第二行", key); 19 | System.out.println(ret); 20 | } 21 | 22 | public static Properties parseIniFile(String filePath) { 23 | Properties properties = new Properties(); 24 | try { 25 | properties.load(new FileInputStream(filePath)); 26 | } catch (IOException e) { 27 | e.printStackTrace(); 28 | } 29 | return properties; 30 | } 31 | 32 | public static String scSend(String var0, String var1, String var2) { 33 | try { 34 | String var3; 35 | 36 | // 判断 sendkey 是否以 "sctp" 开头,并提取数字部分拼接 URL 37 | if (var2.startsWith("sctp")) { 38 | Pattern pattern = Pattern.compile("sctp(\\d+)t"); 39 | Matcher matcher = pattern.matcher(var2); 40 | if (matcher.find()) { 41 | String num = matcher.group(1); 42 | var3 = "https://" + num + ".push.ft07.com/send/" + var2 +".send"; 43 | } else { 44 | throw new IllegalArgumentException("Invalid sendkey format for sctp"); 45 | } 46 | } else { 47 | var3 = "https://sctapi.ftqq.com/" + var2 + ".send"; 48 | } 49 | 50 | String var10000 = URLEncoder.encode(var0, "UTF-8"); 51 | String var4 = "text=" + var10000 + "&desp=" + URLEncoder.encode(var1, "UTF-8"); 52 | URL var5 = new URL(var3); 53 | HttpURLConnection var6 = (HttpURLConnection) var5.openConnection(); 54 | var6.setRequestMethod("POST"); 55 | var6.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 56 | var6.setDoOutput(true); 57 | DataOutputStream var7 = new DataOutputStream(var6.getOutputStream()); 58 | var7.writeBytes(var4); 59 | var7.flush(); 60 | var7.close(); 61 | int var8 = var6.getResponseCode(); 62 | BufferedReader var9 = new BufferedReader(new InputStreamReader(var6.getInputStream())); 63 | StringBuilder var11 = new StringBuilder(); 64 | 65 | String var10; 66 | while ((var10 = var9.readLine()) != null) { 67 | var11.append(var10); 68 | } 69 | 70 | var9.close(); 71 | return var11.toString(); 72 | } catch (Exception var12) { 73 | var12.printStackTrace(); 74 | return null; 75 | } 76 | } 77 | 78 | } -------------------------------------------------------------------------------- /nodejs/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "nodejs", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "dotenv": "^16.3.1", 13 | "https": "^1.0.0" 14 | } 15 | }, 16 | "node_modules/dotenv": { 17 | "version": "16.3.1", 18 | "resolved": "https://registry.npmmirror.com/dotenv/-/dotenv-16.3.1.tgz", 19 | "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", 20 | "engines": { 21 | "node": ">=12" 22 | }, 23 | "funding": { 24 | "url": "https://github.com/motdotla/dotenv?sponsor=1" 25 | } 26 | }, 27 | "node_modules/https": { 28 | "version": "1.0.0", 29 | "resolved": "https://registry.npmmirror.com/https/-/https-1.0.0.tgz", 30 | "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg==" 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /nodejs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "dotenv": "^16.3.1", 8 | "https": "^1.0.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /nodejs/send.js: -------------------------------------------------------------------------------- 1 | const https = require('https'); 2 | const querystring = require('querystring'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | 6 | const data = require('dotenv').parse(fs.readFileSync( path.join(__dirname, '../.env') )); 7 | const key = data.SENDKEY; 8 | 9 | (async () => { 10 | const ret = await sc_send('主人服务器宕机了 via JS', "第一行\n\n第二行", key); 11 | console.log(ret); 12 | })(); 13 | 14 | async function sc_send(text, desp = '', key = '[SENDKEY]') { 15 | const postData = querystring.stringify({ text, desp }); 16 | // 根据 sendkey 是否以 'sctp' 开头,选择不同的 API URL 17 | const url = String(key).match(/^sctp(\d+)t/i) 18 | ? `https://${key.match(/^sctp(\d+)t/i)[1]}.push.ft07.com/send/${key}.send` 19 | : `https://sctapi.ftqq.com/${key}.send`; 20 | 21 | console.log("url", url); 22 | 23 | const response = await fetch(url, { 24 | method: 'POST', 25 | headers: { 26 | 'Content-Type': 'application/x-www-form-urlencoded', 27 | 'Content-Length': Buffer.byteLength(postData) 28 | }, 29 | body: postData 30 | }); 31 | 32 | const data = await response.text(); 33 | return data; 34 | } -------------------------------------------------------------------------------- /nodejs/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | dotenv@^16.3.1: 6 | version "16.3.1" 7 | resolved "https://registry.npmmirror.com/dotenv/-/dotenv-16.3.1.tgz" 8 | integrity sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ== 9 | 10 | https@^1.0.0: 11 | version "1.0.0" 12 | resolved "https://registry.npmmirror.com/https/-/https-1.0.0.tgz" 13 | integrity sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg== 14 | -------------------------------------------------------------------------------- /php/send.php: -------------------------------------------------------------------------------- 1 | $text, 'desp' => $desp )); 12 | 13 | // 判断 $key 是否以 'sctp' 开头,并根据匹配到的数字部分拼接相应的 URL 14 | if (strpos($key, 'sctp') === 0) { 15 | // 使用正则表达式提取 sctp 开头后面的数字 16 | preg_match('/^sctp(\d+)t/', $key, $matches); 17 | $num = $matches[1]; 18 | $url = "https://{$num}.push.ft07.com/send/{$key}.send"; 19 | } else { 20 | $url = "https://sctapi.ftqq.com/{$key}.send"; 21 | } 22 | 23 | $opts = array('http' => 24 | array( 25 | 'method' => 'POST', 26 | 'header' => 'Content-type: application/x-www-form-urlencoded', 27 | 'content' => $postdata)); 28 | 29 | $context = stream_context_create($opts); 30 | return $result = file_get_contents($url, false, $context); 31 | ; 32 | 33 | } 34 | -------------------------------------------------------------------------------- /python/send.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | import re 4 | 5 | def sc_send(sendkey, title, desp='', options=None): 6 | if options is None: 7 | options = {} 8 | # 判断 sendkey 是否以 'sctp' 开头,并提取数字构造 URL 9 | if sendkey.startswith('sctp'): 10 | match = re.match(r'sctp(\d+)t', sendkey) 11 | if match: 12 | num = match.group(1) 13 | url = f'https://{num}.push.ft07.com/send/{sendkey}.send' 14 | else: 15 | raise ValueError('Invalid sendkey format for sctp') 16 | else: 17 | url = f'https://sctapi.ftqq.com/{sendkey}.send' 18 | params = { 19 | 'title': title, 20 | 'desp': desp, 21 | **options 22 | } 23 | headers = { 24 | 'Content-Type': 'application/json;charset=utf-8' 25 | } 26 | response = requests.post(url, json=params, headers=headers) 27 | result = response.json() 28 | return result 29 | 30 | 31 | data = {} 32 | with open(os.path.join(os.path.dirname(__file__), '..', '.env'), 'r') as f: 33 | for line in f: 34 | key, value = line.strip().split('=') 35 | data[key] = value 36 | key = data['SENDKEY'] 37 | 38 | ret = sc_send(key, '主人服务器宕机了 via python', '第一行\n\n第二行') 39 | print(ret) -------------------------------------------------------------------------------- /rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.20.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "autocfg" 31 | version = "1.1.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 34 | 35 | [[package]] 36 | name = "backtrace" 37 | version = "0.3.68" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" 40 | dependencies = [ 41 | "addr2line", 42 | "cc", 43 | "cfg-if", 44 | "libc", 45 | "miniz_oxide", 46 | "object", 47 | "rustc-demangle", 48 | ] 49 | 50 | [[package]] 51 | name = "base64" 52 | version = "0.21.2" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" 55 | 56 | [[package]] 57 | name = "bitflags" 58 | version = "1.3.2" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 61 | 62 | [[package]] 63 | name = "bumpalo" 64 | version = "3.13.0" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" 67 | 68 | [[package]] 69 | name = "bytes" 70 | version = "1.4.0" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" 73 | 74 | [[package]] 75 | name = "cc" 76 | version = "1.0.79" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 79 | 80 | [[package]] 81 | name = "cfg-if" 82 | version = "1.0.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 85 | 86 | [[package]] 87 | name = "core-foundation" 88 | version = "0.9.3" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" 91 | dependencies = [ 92 | "core-foundation-sys", 93 | "libc", 94 | ] 95 | 96 | [[package]] 97 | name = "core-foundation-sys" 98 | version = "0.8.4" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" 101 | 102 | [[package]] 103 | name = "dotenv" 104 | version = "0.15.0" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" 107 | 108 | [[package]] 109 | name = "encoding_rs" 110 | version = "0.8.32" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" 113 | dependencies = [ 114 | "cfg-if", 115 | ] 116 | 117 | [[package]] 118 | name = "errno" 119 | version = "0.3.1" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" 122 | dependencies = [ 123 | "errno-dragonfly", 124 | "libc", 125 | "windows-sys", 126 | ] 127 | 128 | [[package]] 129 | name = "errno-dragonfly" 130 | version = "0.1.2" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 133 | dependencies = [ 134 | "cc", 135 | "libc", 136 | ] 137 | 138 | [[package]] 139 | name = "fastrand" 140 | version = "1.9.0" 141 | source = "registry+https://github.com/rust-lang/crates.io-index" 142 | checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" 143 | dependencies = [ 144 | "instant", 145 | ] 146 | 147 | [[package]] 148 | name = "fnv" 149 | version = "1.0.7" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 152 | 153 | [[package]] 154 | name = "foreign-types" 155 | version = "0.3.2" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 158 | dependencies = [ 159 | "foreign-types-shared", 160 | ] 161 | 162 | [[package]] 163 | name = "foreign-types-shared" 164 | version = "0.1.1" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 167 | 168 | [[package]] 169 | name = "form_urlencoded" 170 | version = "1.2.0" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" 173 | dependencies = [ 174 | "percent-encoding", 175 | ] 176 | 177 | [[package]] 178 | name = "futures-channel" 179 | version = "0.3.28" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" 182 | dependencies = [ 183 | "futures-core", 184 | ] 185 | 186 | [[package]] 187 | name = "futures-core" 188 | version = "0.3.28" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" 191 | 192 | [[package]] 193 | name = "futures-sink" 194 | version = "0.3.28" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" 197 | 198 | [[package]] 199 | name = "futures-task" 200 | version = "0.3.28" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" 203 | 204 | [[package]] 205 | name = "futures-util" 206 | version = "0.3.28" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" 209 | dependencies = [ 210 | "futures-core", 211 | "futures-task", 212 | "pin-project-lite", 213 | "pin-utils", 214 | ] 215 | 216 | [[package]] 217 | name = "gimli" 218 | version = "0.27.3" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" 221 | 222 | [[package]] 223 | name = "h2" 224 | version = "0.3.20" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" 227 | dependencies = [ 228 | "bytes", 229 | "fnv", 230 | "futures-core", 231 | "futures-sink", 232 | "futures-util", 233 | "http", 234 | "indexmap", 235 | "slab", 236 | "tokio", 237 | "tokio-util", 238 | "tracing", 239 | ] 240 | 241 | [[package]] 242 | name = "hashbrown" 243 | version = "0.12.3" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 246 | 247 | [[package]] 248 | name = "hermit-abi" 249 | version = "0.3.2" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" 252 | 253 | [[package]] 254 | name = "http" 255 | version = "0.2.9" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" 258 | dependencies = [ 259 | "bytes", 260 | "fnv", 261 | "itoa", 262 | ] 263 | 264 | [[package]] 265 | name = "http-body" 266 | version = "0.4.5" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 269 | dependencies = [ 270 | "bytes", 271 | "http", 272 | "pin-project-lite", 273 | ] 274 | 275 | [[package]] 276 | name = "httparse" 277 | version = "1.8.0" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 280 | 281 | [[package]] 282 | name = "httpdate" 283 | version = "1.0.2" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 286 | 287 | [[package]] 288 | name = "hyper" 289 | version = "0.14.27" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" 292 | dependencies = [ 293 | "bytes", 294 | "futures-channel", 295 | "futures-core", 296 | "futures-util", 297 | "h2", 298 | "http", 299 | "http-body", 300 | "httparse", 301 | "httpdate", 302 | "itoa", 303 | "pin-project-lite", 304 | "socket2", 305 | "tokio", 306 | "tower-service", 307 | "tracing", 308 | "want", 309 | ] 310 | 311 | [[package]] 312 | name = "hyper-tls" 313 | version = "0.5.0" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 316 | dependencies = [ 317 | "bytes", 318 | "hyper", 319 | "native-tls", 320 | "tokio", 321 | "tokio-native-tls", 322 | ] 323 | 324 | [[package]] 325 | name = "idna" 326 | version = "0.4.0" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" 329 | dependencies = [ 330 | "unicode-bidi", 331 | "unicode-normalization", 332 | ] 333 | 334 | [[package]] 335 | name = "indexmap" 336 | version = "1.9.3" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 339 | dependencies = [ 340 | "autocfg", 341 | "hashbrown", 342 | ] 343 | 344 | [[package]] 345 | name = "instant" 346 | version = "0.1.12" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 349 | dependencies = [ 350 | "cfg-if", 351 | ] 352 | 353 | [[package]] 354 | name = "io-lifetimes" 355 | version = "1.0.11" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" 358 | dependencies = [ 359 | "hermit-abi", 360 | "libc", 361 | "windows-sys", 362 | ] 363 | 364 | [[package]] 365 | name = "ipnet" 366 | version = "2.8.0" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" 369 | 370 | [[package]] 371 | name = "itoa" 372 | version = "1.0.9" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" 375 | 376 | [[package]] 377 | name = "js-sys" 378 | version = "0.3.64" 379 | source = "registry+https://github.com/rust-lang/crates.io-index" 380 | checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" 381 | dependencies = [ 382 | "wasm-bindgen", 383 | ] 384 | 385 | [[package]] 386 | name = "lazy_static" 387 | version = "1.4.0" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 390 | 391 | [[package]] 392 | name = "libc" 393 | version = "0.2.147" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" 396 | 397 | [[package]] 398 | name = "linux-raw-sys" 399 | version = "0.3.8" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" 402 | 403 | [[package]] 404 | name = "lock_api" 405 | version = "0.4.10" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" 408 | dependencies = [ 409 | "autocfg", 410 | "scopeguard", 411 | ] 412 | 413 | [[package]] 414 | name = "log" 415 | version = "0.4.19" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" 418 | 419 | [[package]] 420 | name = "memchr" 421 | version = "2.7.4" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 424 | 425 | [[package]] 426 | name = "mime" 427 | version = "0.3.17" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 430 | 431 | [[package]] 432 | name = "miniz_oxide" 433 | version = "0.7.1" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" 436 | dependencies = [ 437 | "adler", 438 | ] 439 | 440 | [[package]] 441 | name = "mio" 442 | version = "0.8.8" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" 445 | dependencies = [ 446 | "libc", 447 | "wasi", 448 | "windows-sys", 449 | ] 450 | 451 | [[package]] 452 | name = "native-tls" 453 | version = "0.2.11" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" 456 | dependencies = [ 457 | "lazy_static", 458 | "libc", 459 | "log", 460 | "openssl", 461 | "openssl-probe", 462 | "openssl-sys", 463 | "schannel", 464 | "security-framework", 465 | "security-framework-sys", 466 | "tempfile", 467 | ] 468 | 469 | [[package]] 470 | name = "num_cpus" 471 | version = "1.16.0" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 474 | dependencies = [ 475 | "hermit-abi", 476 | "libc", 477 | ] 478 | 479 | [[package]] 480 | name = "object" 481 | version = "0.31.1" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" 484 | dependencies = [ 485 | "memchr", 486 | ] 487 | 488 | [[package]] 489 | name = "once_cell" 490 | version = "1.17.2" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" 493 | 494 | [[package]] 495 | name = "openssl" 496 | version = "0.10.55" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" 499 | dependencies = [ 500 | "bitflags", 501 | "cfg-if", 502 | "foreign-types", 503 | "libc", 504 | "once_cell", 505 | "openssl-macros", 506 | "openssl-sys", 507 | ] 508 | 509 | [[package]] 510 | name = "openssl-macros" 511 | version = "0.1.1" 512 | source = "registry+https://github.com/rust-lang/crates.io-index" 513 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 514 | dependencies = [ 515 | "proc-macro2", 516 | "quote", 517 | "syn", 518 | ] 519 | 520 | [[package]] 521 | name = "openssl-probe" 522 | version = "0.1.5" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 525 | 526 | [[package]] 527 | name = "openssl-sys" 528 | version = "0.9.90" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" 531 | dependencies = [ 532 | "cc", 533 | "libc", 534 | "pkg-config", 535 | "vcpkg", 536 | ] 537 | 538 | [[package]] 539 | name = "parking_lot" 540 | version = "0.12.1" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 543 | dependencies = [ 544 | "lock_api", 545 | "parking_lot_core", 546 | ] 547 | 548 | [[package]] 549 | name = "parking_lot_core" 550 | version = "0.9.8" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" 553 | dependencies = [ 554 | "cfg-if", 555 | "libc", 556 | "redox_syscall", 557 | "smallvec", 558 | "windows-targets", 559 | ] 560 | 561 | [[package]] 562 | name = "percent-encoding" 563 | version = "2.3.0" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" 566 | 567 | [[package]] 568 | name = "pin-project-lite" 569 | version = "0.2.10" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" 572 | 573 | [[package]] 574 | name = "pin-utils" 575 | version = "0.1.0" 576 | source = "registry+https://github.com/rust-lang/crates.io-index" 577 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 578 | 579 | [[package]] 580 | name = "pkg-config" 581 | version = "0.3.27" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" 584 | 585 | [[package]] 586 | name = "proc-macro2" 587 | version = "1.0.65" 588 | source = "registry+https://github.com/rust-lang/crates.io-index" 589 | checksum = "92de25114670a878b1261c79c9f8f729fb97e95bac93f6312f583c60dd6a1dfe" 590 | dependencies = [ 591 | "unicode-ident", 592 | ] 593 | 594 | [[package]] 595 | name = "quote" 596 | version = "1.0.30" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | checksum = "5907a1b7c277254a8b15170f6e7c97cfa60ee7872a3217663bb81151e48184bb" 599 | dependencies = [ 600 | "proc-macro2", 601 | ] 602 | 603 | [[package]] 604 | name = "redox_syscall" 605 | version = "0.3.5" 606 | source = "registry+https://github.com/rust-lang/crates.io-index" 607 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 608 | dependencies = [ 609 | "bitflags", 610 | ] 611 | 612 | [[package]] 613 | name = "regex" 614 | version = "1.11.0" 615 | source = "registry+https://github.com/rust-lang/crates.io-index" 616 | checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" 617 | dependencies = [ 618 | "aho-corasick", 619 | "memchr", 620 | "regex-automata", 621 | "regex-syntax", 622 | ] 623 | 624 | [[package]] 625 | name = "regex-automata" 626 | version = "0.4.8" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" 629 | dependencies = [ 630 | "aho-corasick", 631 | "memchr", 632 | "regex-syntax", 633 | ] 634 | 635 | [[package]] 636 | name = "regex-syntax" 637 | version = "0.8.5" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 640 | 641 | [[package]] 642 | name = "reqwest" 643 | version = "0.11.18" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" 646 | dependencies = [ 647 | "base64", 648 | "bytes", 649 | "encoding_rs", 650 | "futures-core", 651 | "futures-util", 652 | "h2", 653 | "http", 654 | "http-body", 655 | "hyper", 656 | "hyper-tls", 657 | "ipnet", 658 | "js-sys", 659 | "log", 660 | "mime", 661 | "native-tls", 662 | "once_cell", 663 | "percent-encoding", 664 | "pin-project-lite", 665 | "serde", 666 | "serde_json", 667 | "serde_urlencoded", 668 | "tokio", 669 | "tokio-native-tls", 670 | "tower-service", 671 | "url", 672 | "wasm-bindgen", 673 | "wasm-bindgen-futures", 674 | "web-sys", 675 | "winreg", 676 | ] 677 | 678 | [[package]] 679 | name = "rustc-demangle" 680 | version = "0.1.23" 681 | source = "registry+https://github.com/rust-lang/crates.io-index" 682 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 683 | 684 | [[package]] 685 | name = "rustix" 686 | version = "0.37.23" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" 689 | dependencies = [ 690 | "bitflags", 691 | "errno", 692 | "io-lifetimes", 693 | "libc", 694 | "linux-raw-sys", 695 | "windows-sys", 696 | ] 697 | 698 | [[package]] 699 | name = "ryu" 700 | version = "1.0.15" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" 703 | 704 | [[package]] 705 | name = "schannel" 706 | version = "0.1.22" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" 709 | dependencies = [ 710 | "windows-sys", 711 | ] 712 | 713 | [[package]] 714 | name = "scopeguard" 715 | version = "1.1.0" 716 | source = "registry+https://github.com/rust-lang/crates.io-index" 717 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 718 | 719 | [[package]] 720 | name = "security-framework" 721 | version = "2.8.1" 722 | source = "registry+https://github.com/rust-lang/crates.io-index" 723 | checksum = "7c4437699b6d34972de58652c68b98cb5b53a4199ab126db8e20ec8ded29a721" 724 | dependencies = [ 725 | "bitflags", 726 | "core-foundation", 727 | "core-foundation-sys", 728 | "libc", 729 | "security-framework-sys", 730 | ] 731 | 732 | [[package]] 733 | name = "security-framework-sys" 734 | version = "2.9.0" 735 | source = "registry+https://github.com/rust-lang/crates.io-index" 736 | checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" 737 | dependencies = [ 738 | "core-foundation-sys", 739 | "libc", 740 | ] 741 | 742 | [[package]] 743 | name = "serde" 744 | version = "1.0.171" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" 747 | 748 | [[package]] 749 | name = "serde_json" 750 | version = "1.0.103" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" 753 | dependencies = [ 754 | "itoa", 755 | "ryu", 756 | "serde", 757 | ] 758 | 759 | [[package]] 760 | name = "serde_urlencoded" 761 | version = "0.7.1" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 764 | dependencies = [ 765 | "form_urlencoded", 766 | "itoa", 767 | "ryu", 768 | "serde", 769 | ] 770 | 771 | [[package]] 772 | name = "server_chan" 773 | version = "0.1.0" 774 | dependencies = [ 775 | "dotenv", 776 | "regex", 777 | "reqwest", 778 | "serde_urlencoded", 779 | "tokio", 780 | ] 781 | 782 | [[package]] 783 | name = "signal-hook-registry" 784 | version = "1.4.1" 785 | source = "registry+https://github.com/rust-lang/crates.io-index" 786 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 787 | dependencies = [ 788 | "libc", 789 | ] 790 | 791 | [[package]] 792 | name = "slab" 793 | version = "0.4.8" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" 796 | dependencies = [ 797 | "autocfg", 798 | ] 799 | 800 | [[package]] 801 | name = "smallvec" 802 | version = "1.11.0" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" 805 | 806 | [[package]] 807 | name = "socket2" 808 | version = "0.4.9" 809 | source = "registry+https://github.com/rust-lang/crates.io-index" 810 | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" 811 | dependencies = [ 812 | "libc", 813 | "winapi", 814 | ] 815 | 816 | [[package]] 817 | name = "syn" 818 | version = "2.0.26" 819 | source = "registry+https://github.com/rust-lang/crates.io-index" 820 | checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" 821 | dependencies = [ 822 | "proc-macro2", 823 | "quote", 824 | "unicode-ident", 825 | ] 826 | 827 | [[package]] 828 | name = "tempfile" 829 | version = "3.6.0" 830 | source = "registry+https://github.com/rust-lang/crates.io-index" 831 | checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" 832 | dependencies = [ 833 | "autocfg", 834 | "cfg-if", 835 | "fastrand", 836 | "redox_syscall", 837 | "rustix", 838 | "windows-sys", 839 | ] 840 | 841 | [[package]] 842 | name = "tinyvec" 843 | version = "1.6.0" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 846 | dependencies = [ 847 | "tinyvec_macros", 848 | ] 849 | 850 | [[package]] 851 | name = "tinyvec_macros" 852 | version = "0.1.1" 853 | source = "registry+https://github.com/rust-lang/crates.io-index" 854 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 855 | 856 | [[package]] 857 | name = "tokio" 858 | version = "1.29.1" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" 861 | dependencies = [ 862 | "autocfg", 863 | "backtrace", 864 | "bytes", 865 | "libc", 866 | "mio", 867 | "num_cpus", 868 | "parking_lot", 869 | "pin-project-lite", 870 | "signal-hook-registry", 871 | "socket2", 872 | "tokio-macros", 873 | "windows-sys", 874 | ] 875 | 876 | [[package]] 877 | name = "tokio-macros" 878 | version = "2.1.0" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" 881 | dependencies = [ 882 | "proc-macro2", 883 | "quote", 884 | "syn", 885 | ] 886 | 887 | [[package]] 888 | name = "tokio-native-tls" 889 | version = "0.3.1" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 892 | dependencies = [ 893 | "native-tls", 894 | "tokio", 895 | ] 896 | 897 | [[package]] 898 | name = "tokio-util" 899 | version = "0.7.8" 900 | source = "registry+https://github.com/rust-lang/crates.io-index" 901 | checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" 902 | dependencies = [ 903 | "bytes", 904 | "futures-core", 905 | "futures-sink", 906 | "pin-project-lite", 907 | "tokio", 908 | "tracing", 909 | ] 910 | 911 | [[package]] 912 | name = "tower-service" 913 | version = "0.3.2" 914 | source = "registry+https://github.com/rust-lang/crates.io-index" 915 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 916 | 917 | [[package]] 918 | name = "tracing" 919 | version = "0.1.37" 920 | source = "registry+https://github.com/rust-lang/crates.io-index" 921 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 922 | dependencies = [ 923 | "cfg-if", 924 | "pin-project-lite", 925 | "tracing-core", 926 | ] 927 | 928 | [[package]] 929 | name = "tracing-core" 930 | version = "0.1.31" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" 933 | dependencies = [ 934 | "once_cell", 935 | ] 936 | 937 | [[package]] 938 | name = "try-lock" 939 | version = "0.2.4" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" 942 | 943 | [[package]] 944 | name = "unicode-bidi" 945 | version = "0.3.13" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" 948 | 949 | [[package]] 950 | name = "unicode-ident" 951 | version = "1.0.11" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" 954 | 955 | [[package]] 956 | name = "unicode-normalization" 957 | version = "0.1.22" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 960 | dependencies = [ 961 | "tinyvec", 962 | ] 963 | 964 | [[package]] 965 | name = "url" 966 | version = "2.4.0" 967 | source = "registry+https://github.com/rust-lang/crates.io-index" 968 | checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" 969 | dependencies = [ 970 | "form_urlencoded", 971 | "idna", 972 | "percent-encoding", 973 | ] 974 | 975 | [[package]] 976 | name = "vcpkg" 977 | version = "0.2.15" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 980 | 981 | [[package]] 982 | name = "want" 983 | version = "0.3.1" 984 | source = "registry+https://github.com/rust-lang/crates.io-index" 985 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 986 | dependencies = [ 987 | "try-lock", 988 | ] 989 | 990 | [[package]] 991 | name = "wasi" 992 | version = "0.11.0+wasi-snapshot-preview1" 993 | source = "registry+https://github.com/rust-lang/crates.io-index" 994 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 995 | 996 | [[package]] 997 | name = "wasm-bindgen" 998 | version = "0.2.87" 999 | source = "registry+https://github.com/rust-lang/crates.io-index" 1000 | checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" 1001 | dependencies = [ 1002 | "cfg-if", 1003 | "wasm-bindgen-macro", 1004 | ] 1005 | 1006 | [[package]] 1007 | name = "wasm-bindgen-backend" 1008 | version = "0.2.87" 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" 1010 | checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" 1011 | dependencies = [ 1012 | "bumpalo", 1013 | "log", 1014 | "once_cell", 1015 | "proc-macro2", 1016 | "quote", 1017 | "syn", 1018 | "wasm-bindgen-shared", 1019 | ] 1020 | 1021 | [[package]] 1022 | name = "wasm-bindgen-futures" 1023 | version = "0.4.37" 1024 | source = "registry+https://github.com/rust-lang/crates.io-index" 1025 | checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" 1026 | dependencies = [ 1027 | "cfg-if", 1028 | "js-sys", 1029 | "wasm-bindgen", 1030 | "web-sys", 1031 | ] 1032 | 1033 | [[package]] 1034 | name = "wasm-bindgen-macro" 1035 | version = "0.2.87" 1036 | source = "registry+https://github.com/rust-lang/crates.io-index" 1037 | checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" 1038 | dependencies = [ 1039 | "quote", 1040 | "wasm-bindgen-macro-support", 1041 | ] 1042 | 1043 | [[package]] 1044 | name = "wasm-bindgen-macro-support" 1045 | version = "0.2.87" 1046 | source = "registry+https://github.com/rust-lang/crates.io-index" 1047 | checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" 1048 | dependencies = [ 1049 | "proc-macro2", 1050 | "quote", 1051 | "syn", 1052 | "wasm-bindgen-backend", 1053 | "wasm-bindgen-shared", 1054 | ] 1055 | 1056 | [[package]] 1057 | name = "wasm-bindgen-shared" 1058 | version = "0.2.87" 1059 | source = "registry+https://github.com/rust-lang/crates.io-index" 1060 | checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" 1061 | 1062 | [[package]] 1063 | name = "web-sys" 1064 | version = "0.3.64" 1065 | source = "registry+https://github.com/rust-lang/crates.io-index" 1066 | checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" 1067 | dependencies = [ 1068 | "js-sys", 1069 | "wasm-bindgen", 1070 | ] 1071 | 1072 | [[package]] 1073 | name = "winapi" 1074 | version = "0.3.9" 1075 | source = "registry+https://github.com/rust-lang/crates.io-index" 1076 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1077 | dependencies = [ 1078 | "winapi-i686-pc-windows-gnu", 1079 | "winapi-x86_64-pc-windows-gnu", 1080 | ] 1081 | 1082 | [[package]] 1083 | name = "winapi-i686-pc-windows-gnu" 1084 | version = "0.4.0" 1085 | source = "registry+https://github.com/rust-lang/crates.io-index" 1086 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1087 | 1088 | [[package]] 1089 | name = "winapi-x86_64-pc-windows-gnu" 1090 | version = "0.4.0" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1093 | 1094 | [[package]] 1095 | name = "windows-sys" 1096 | version = "0.48.0" 1097 | source = "registry+https://github.com/rust-lang/crates.io-index" 1098 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1099 | dependencies = [ 1100 | "windows-targets", 1101 | ] 1102 | 1103 | [[package]] 1104 | name = "windows-targets" 1105 | version = "0.48.1" 1106 | source = "registry+https://github.com/rust-lang/crates.io-index" 1107 | checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" 1108 | dependencies = [ 1109 | "windows_aarch64_gnullvm", 1110 | "windows_aarch64_msvc", 1111 | "windows_i686_gnu", 1112 | "windows_i686_msvc", 1113 | "windows_x86_64_gnu", 1114 | "windows_x86_64_gnullvm", 1115 | "windows_x86_64_msvc", 1116 | ] 1117 | 1118 | [[package]] 1119 | name = "windows_aarch64_gnullvm" 1120 | version = "0.48.0" 1121 | source = "registry+https://github.com/rust-lang/crates.io-index" 1122 | checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" 1123 | 1124 | [[package]] 1125 | name = "windows_aarch64_msvc" 1126 | version = "0.48.0" 1127 | source = "registry+https://github.com/rust-lang/crates.io-index" 1128 | checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" 1129 | 1130 | [[package]] 1131 | name = "windows_i686_gnu" 1132 | version = "0.48.0" 1133 | source = "registry+https://github.com/rust-lang/crates.io-index" 1134 | checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" 1135 | 1136 | [[package]] 1137 | name = "windows_i686_msvc" 1138 | version = "0.48.0" 1139 | source = "registry+https://github.com/rust-lang/crates.io-index" 1140 | checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" 1141 | 1142 | [[package]] 1143 | name = "windows_x86_64_gnu" 1144 | version = "0.48.0" 1145 | source = "registry+https://github.com/rust-lang/crates.io-index" 1146 | checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" 1147 | 1148 | [[package]] 1149 | name = "windows_x86_64_gnullvm" 1150 | version = "0.48.0" 1151 | source = "registry+https://github.com/rust-lang/crates.io-index" 1152 | checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" 1153 | 1154 | [[package]] 1155 | name = "windows_x86_64_msvc" 1156 | version = "0.48.0" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" 1159 | 1160 | [[package]] 1161 | name = "winreg" 1162 | version = "0.10.1" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" 1165 | dependencies = [ 1166 | "winapi", 1167 | ] 1168 | -------------------------------------------------------------------------------- /rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "server_chan" 3 | version = "0.1.0" 4 | authors = ["EasyChen "] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | reqwest = "0.11" 9 | serde_urlencoded = "0.7" 10 | tokio = { version = "1", features = ["full"] } 11 | dotenv = "0.15.0" 12 | regex = "1.11.0" 13 | -------------------------------------------------------------------------------- /rust/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use reqwest::header::{CONTENT_TYPE, CONTENT_LENGTH}; 3 | use serde_urlencoded; 4 | use tokio; 5 | use regex::Regex; 6 | 7 | #[tokio::main] 8 | async fn main() -> Result<(), Box> { 9 | dotenv::dotenv().ok(); 10 | let key = env::var("SENDKEY").unwrap(); 11 | let ret = sc_send("主人服务器宕机了 via Rust".to_string(), "第一行\n\n第二行".to_string(), key).await?; 12 | println!("{}", ret); 13 | Ok(()) 14 | } 15 | 16 | async fn sc_send(text: String, desp: String, key: String) -> Result> { 17 | let params = [("text", text), ("desp", desp)]; 18 | let post_data = serde_urlencoded::to_string(params)?; 19 | // 使用正则表达式提取 key 中的数字部分 20 | let url = if key.starts_with("sctp") { 21 | let re = Regex::new(r"sctp(\d+)t")?; 22 | if let Some(captures) = re.captures(&key) { 23 | let num = &captures[1]; // 提取正则表达式捕获的数字部分 24 | format!("https://{}.push.ft07.com/send/{}.send", num, key) 25 | } else { 26 | return Err("Invalid sendkey format for sctp".into()); 27 | } 28 | } else { 29 | format!("https://sctapi.ftqq.com/{}.send", key) 30 | }; 31 | let client = reqwest::Client::new(); 32 | let res = client.post(&url) 33 | .header(CONTENT_TYPE, "application/x-www-form-urlencoded") 34 | .header(CONTENT_LENGTH, post_data.len() as u64) 35 | .body(post_data) 36 | .send() 37 | .await?; 38 | let data = res.text().await?; 39 | Ok(data) 40 | } -------------------------------------------------------------------------------- /shell/send.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function sc_send() { 4 | local text=$1 5 | local desp=$2 6 | local key=$3 7 | 8 | postdata="text=$text&desp=$desp" 9 | opts=( 10 | "--header" "Content-type: application/x-www-form-urlencoded" 11 | "--data" "$postdata" 12 | ) 13 | 14 | # 判断 key 是否以 "sctp" 开头,选择不同的 URL 15 | if [[ "$key" =~ ^sctp([0-9]+)t ]]; then 16 | # 使用正则表达式提取数字部分 17 | num=${BASH_REMATCH[1]} 18 | url="https://${num}.push.ft07.com/send/${key}.send" 19 | else 20 | url="https://sctapi.ftqq.com/${key}.send" 21 | fi 22 | 23 | 24 | # 使用动态生成的 url 发送请求 25 | result=$(curl -X POST -s -o /dev/null -w "%{http_code}" "$url" "${opts[@]}") 26 | echo "$result" 27 | } 28 | 29 | # 读取配置文件 30 | data=$(cat "$PWD/../.env") 31 | eval "$data" 32 | 33 | # 调用sc_send函数 34 | ret=$(sc_send '主人服务器宕机了 via shell' $'第一行\n\n第二行' "$SENDKEY") 35 | echo "$ret" 36 | 37 | -------------------------------------------------------------------------------- /swift/main.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | func sc_send(text: String, desp: String = "", key: String = "[SENDKEY]") -> String { 4 | let urlString: String 5 | let regex = try! NSRegularExpression(pattern: "^sctp(\\d+)t", options: []) 6 | 7 | if key.hasPrefix("sctp") { 8 | if let match = regex.firstMatch(in: key, options: [], range: NSRange(location: 0, length: key.utf16.count)) { 9 | let numRange = match.range(at: 1) 10 | if let numRange = Range(numRange, in: key) { 11 | let num = key[numRange] 12 | urlString = "https://\(num).push.ft07.com/send/\(key).send" 13 | } else { 14 | // 处理错误:没有提取到数字 15 | fatalError("Invalid key format") 16 | } 17 | } else { 18 | // 处理错误:正则匹配失败 19 | fatalError("Invalid key format") 20 | } 21 | } else { 22 | urlString = "https://sctapi.ftqq.com/\(key).send" 23 | } 24 | 25 | guard let url = URL(string: urlString) else { 26 | print("Invalid URL") 27 | return "" 28 | } 29 | var request = URLRequest(url: url) 30 | request.httpMethod = "POST" 31 | request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") 32 | let postdata = "text=\(text)&desp=\(desp)" 33 | request.httpBody = postdata.data(using: .utf8) 34 | 35 | let semaphore = DispatchSemaphore(value: 0) 36 | var result = "" 37 | 38 | let task = URLSession.shared.dataTask(with: request) { (data, response, error) in 39 | if let error = error { 40 | print("Error: \(error)") 41 | } else if let data = data { 42 | result = String(data: data, encoding: .utf8) ?? "" 43 | } 44 | semaphore.signal() 45 | } 46 | task.resume() 47 | semaphore.wait() 48 | 49 | return result 50 | } 51 | 52 | let data = try! String(contentsOfFile: "\(FileManager.default.currentDirectoryPath)/../.env", encoding: .utf8) 53 | let lines = data.components(separatedBy: .newlines) 54 | var key = "" 55 | for line in lines { 56 | if line.hasPrefix("SENDKEY=") { 57 | key = line.replacingOccurrences(of: "SENDKEY=", with: "") 58 | break 59 | } 60 | } 61 | 62 | let ret = sc_send(text: "主人服务器宕机了 via swift", desp: "第一行\n\n第二行", key: key) 63 | print(ret) --------------------------------------------------------------------------------