Compare commits

..

No commits in common. "cffada6b3b48cf9b2fcf3fdb52025e22ecfed58a" and "263c95de668e5eed4588d5c727e3318d78609423" have entirely different histories.

18 changed files with 638 additions and 1565 deletions

View file

@ -1,31 +0,0 @@
---
name: Bug
about: Create a bug report to help us improve Telepingbot
title: '...'
labels: ["Kind/Bug"]
assignees: ''
---
## Checks
* [ ] I added a descriptive title to this issue
* [ ] I have searched Google for similar issues and couldn't find anything
* [ ] I have read [the README](https://git.4rs.nl/awiteb/telepingbot/src/branch/master/README.md) and still think this is a bug
## Version
<!-- Report for the bug only if it's present in the latest version of Telepingbot.
If you are not using the latest version, please update and check if the bug is still present. -->
<!-- Run `rustc --version` to get the version -->
Rustc version: `...`
<!-- Run `telepingbot --version` to get the version, and make sure it's the latest one -->
Telepingbot version: `...`
## Description
<!-- A clear and concise description of what the bug is. -->
## Expected behavior
<!-- A clear and concise description of what you expected to happen. -->
## Actual behavior
<!-- A clear and concise description of what happens. -->

View file

@ -1,13 +0,0 @@
---
name: Feature request
about: Suggest an idea for Telepingbot
title: '...'
labels: ["Kind/Feature"]
assignees: ''
---
## Feature description
<!-- A clear and concise description of what the feature is, and why you think it is needed. -->
## Example
<!-- A clear and concise example of how the feature will be used. (If needed) -->

View file

@ -1,12 +0,0 @@
---
name: Question
about: Ask a question about Telepingbot
title: '...'
labels: ["Kind/Question"]
assignees: ''
---
## Question
<!-- Please provide a clear and concise description of your question. -->
<!-- If you are asking about a specific part of the code, please provide a link to the code. -->
<!-- If you are asking about a specific part of the documentation, please provide a link to the documentation. -->

View file

@ -1,6 +0,0 @@
## Issue
<!-- Copy the issue link from the issue you are fixing (e.g. https://git.4rs.nl/awiteb/telepingbot/issues/1) -->
This will fix {issue Forgejo link}
## How I am fixing it
<!-- A clear and concise description of how you are fixing the bug. -->

View file

@ -1,112 +0,0 @@
name: CD
on:
push:
tags:
- v[0-9]+.[0-9]+.[0-9]+
- v[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+
jobs:
build-assets:
runs-on: debian
strategy:
matrix:
target:
- x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl
- aarch64-unknown-linux-gnu
- aarch64-unknown-linux-musl
- x86_64-pc-windows-gnu
steps:
- uses: actions/checkout@v4
with:
ref: master
fetch-depth: 1
- uses: https://codeberg.org/TheAwiteb/rust-action@v1.75
- name: Install musl-tools
run: |
apt-get update
apt-get install -y musl-tools
if: ${{ contains(matrix.target, 'musl') }}
- name: Install gcc-aarch64-linux-gnu linker
run: |
apt-get update
apt-get install -y gcc-aarch64-linux-gnu
if: ${{ contains(matrix.target, 'aarch64') }}
- name: Install gcc-mingw-w64 linker
run: |
apt-get update
apt-get install -y gcc-mingw-w64
if: ${{ contains(matrix.target, 'windows') }}
- name: Preparing the environment
run: |
BIN_NAME="$(echo $GITHUB_REPOSITORY | cut -d '/' -f 2)"
echo "BIN_NAME=$BIN_NAME" >> $GITHUB_ENV
mkdir -p release-dir
mkdir -p .cargo
echo 'target.aarch64-unknown-linux-gnu.linker = "aarch64-linux-gnu-gcc"' > .cargo/config.toml
echo 'target.aarch64-unknown-linux-musl.linker = "aarch64-linux-gnu-gcc"' >> .cargo/config.toml
- name: Install the target
run: rustup target install ${{ matrix.target }}
- name: Build the asset
run: |
APP_NAME="$BIN_NAME-$GITHUB_REF_NAME-${{ matrix.target }}"
cargo clean
cargo build --release --no-default-features --target ${{ matrix.target }}
cp target/${{ matrix.target }}/release/$BIN_NAME.exe release-dir/$APP_NAME.exe || true
cp target/${{ matrix.target }}/release/$BIN_NAME release-dir/$APP_NAME || true
cd release-dir
test -f $APP_NAME && sha256sum $APP_NAME > $APP_NAME.sha256 || true
test -f $APP_NAME.exe && sha256sum $APP_NAME.exe > $APP_NAME.exe.sha256 || true
- uses: actions/upload-artifact@v3
with:
name: ${{ env.GITHUB_SHA }}-${{ env.GITHUB_RUN_NUMBER }}
path: release-dir/
release:
needs: build-assets
runs-on: debian
steps:
- uses: actions/checkout@v4
with:
ref: master
fetch-depth: 0
fetch-tags: true
- uses: actions/download-artifact@v3
with:
name: ${{ env.GITHUB_SHA }}-${{ env.GITHUB_RUN_NUMBER }}
path: ${{ env.GITHUB_WORKSPACE }}/release-dir
- name: Install git-cliff
run: |
version="2.2.1"
wget "https://github.com/orhun/git-cliff/releases/download/v$version/git-cliff-$version-x86_64-unknown-linux-gnu.tar.gz"
tar -xvzf git-cliff-*.tar.gz
mv "git-cliff-$version/git-cliff" /usr/local/bin
rm -fr git-cliff-*
- name: Write changelog
run: |
git config user.name forgejo-actions
git config user.email forgejo-actions@noreply.localhost
echo 'TAG_CHANGELOG=$(if [[ $(git tag --sort=committerdate | tail -n 1) == *"-rc"* ]]; then git-cliff --strip all $(git tag --sort=committerdate | tail -n 2 | sed ":a; N; $!ba; s/\n/../g") | sed "s/## unreleased.*$//g"; else git-cliff -l --strip all | sed "s/^## \[.*$//g";fi)' | sed "s/\"/'/g" >> $GITHUB_ENV
if [[ $(git tag --sort=creatordate | tail -n 1) != *'-rc'* ]]; then
echo "The latest tag is not a release candidate, updating changelog for $GITHUB_REF_NAME"
git-cliff > CHANGELOG.md
git add CHANGELOG.md
git commit -m "Update changelog for $GITHUB_REF_NAME"
git push
echo "Changelog updated"
else
echo "The latest tag is a release candidate, not updating changelog"
fi
- name: Create Release
uses: actions/forgejo-release@v1
with:
direction: upload
url: https://git.4rs.nl
token: ${{ env.GITHUB_TOKEN }}
release-dir: release-dir
release-notes: ${{ env.TAG_CHANGELOG }}
prerelease: ${{ contains(env.GITHUB_REF_NAME, '-rc') }}

View file

@ -1,36 +0,0 @@
name: Write changelog
on:
push:
branches:
- 'master'
jobs:
write-changelog:
runs-on: debian
steps:
- uses: actions/checkout@v4
with:
ref: master
fetch-depth: 0
fetch-tags: true
- name: Install git-cliff
run: |
version="2.2.1"
wget "https://github.com/orhun/git-cliff/releases/download/v$version/git-cliff-$version-x86_64-unknown-linux-gnu.tar.gz"
tar -xvzf git-cliff-*.tar.gz
mv "git-cliff-$version/git-cliff" /usr/local/bin
rm -fr git-cliff-*
- name: Write changelog
run: |
git config user.name forgejo-actions
git config user.email forgejo-actions@noreply.localhost
git-cliff > CHANGELOG.md
if [[ $(git status | grep --extended-regexp '^\s+modified:\s+CHANGELOG.md$') ]]; then
git add CHANGELOG.md
git commit -m "chore(changelog): Update changelog"
git push
echo "Changelog updated"
else
echo "No changes to changelog"
fi

View file

@ -1,25 +0,0 @@
name: Rust CI
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
rust_ci:
name: Rust CI
runs-on: debian
steps:
- uses: actions/checkout@v4
- uses: https://codeberg.org/TheAwiteb/rust-action@v1.75
- name: Check MSRV
run: cargo +1.75 build
- name: Build the source code
run: cargo build
- name: Check the code format
run: cargo fmt -- --check
- name: Run cargo-check
run: cargo check
- name: Run cargo-clippy
run: cargo clippy -- -D warnings

View file

@ -1,34 +0,0 @@
name: Auto close PR
on:
pull_request:
types: [opened, reopened]
jobs:
close_pr:
name: Auto close PR
runs-on: ubuntu-latest
steps:
- name: Send close comment
run: |
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $PAT" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.number }}/comments \
-d '{"body":"${{ env.BODY }}"}'
env:
PAT: ${{ secrets.PAT }}
BODY: This repository is mirror only and you cannot create a pull request for it. Please open your PR at https://git.4rs.nl/awiteb/telepingbot
- name: Close the PR
run: |
curl -L \
-X PATCH \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $PAT" \
-H "X-GitHub-Api-Version: 2022-11-28" \
https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.number }} \
-d '{"state":"closed"}'
env:
PAT: ${{ secrets.PAT }}

View file

@ -1,11 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## unreleased
## 0.1.0 - 2023-11-18
This changelog was generated by [git-cliff](https://github.com/orhun/git-cliff)

1569
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,80 +1,27 @@
[package]
authors = ["Awiteb <a@4rs.nl>"]
authors = ["TheAwiteb <awiteb@hotmail.com>"]
description = "Simple API to ping a telegram bot using superbot (mtproto)"
edition = "2021"
license = "AGPL-3.0-or-later"
name = "telepingbot"
readme = "README.md"
repository = "https://git.4rs.nl/awiteb/telepingbot"
rust-version = "1.75.0"
repository = "https://github.com/TheAwiteb/telepingbot"
rust-version = "1.68.2"
version = "0.1.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4.38"
chrono = "0.4.31"
dotenv = "0.15.0"
grammers-client = "0.6.0"
grammers-session = "0.5.2"
grammers-client = "= 0.4.0"
grammers-session = "= 0.4.0"
lazy_static = "1.4.0"
log = "0.4.21"
log = "0.4.20"
pretty_env_logger = "0.5.0"
promptly = "0.3.1"
salvo = {version = "0.67.2", features = ["logging", "affix", "rustls"]}
serde = {version = "1.0.202", features = ["derive"]}
serde_json = "1.0.117"
sha256 = "1.5.0"
tokio = {version = "1.37.0", features = ["macros", "rt-multi-thread", "signal"]}
[lints.rust]
unsafe_code = "forbid"
missing_docs = "warn"
[lints.clippy]
# I know is huge, but I like to be explicit, it also provides
# a better DX for new contributors (Make it easier to understand the codebase).
# Also, this is a general linting configuration, it's not specific to this project.
wildcard_imports = "deny"
manual_let_else = "deny"
match_bool = "deny"
match_on_vec_items = "deny"
or_fun_call = "deny"
panic = "deny"
unwrap_used = "deny"
missing_assert_message = "warn"
missing_const_for_fn = "warn"
missing_errors_doc = "warn"
absolute_paths = "warn"
cast_lossless = "warn"
clone_on_ref_ptr = "warn"
cloned_instead_of_copied = "warn"
dbg_macro = "warn"
default_trait_access = "warn"
empty_enum_variants_with_brackets = "warn"
empty_line_after_doc_comments = "warn"
empty_line_after_outer_attr = "warn"
empty_structs_with_brackets = "warn"
enum_glob_use = "warn"
equatable_if_let = "warn"
explicit_iter_loop = "warn"
filetype_is_file = "warn"
filter_map_next = "warn"
flat_map_option = "warn"
float_cmp = "warn"
format_push_string = "warn"
future_not_send = "warn"
if_not_else = "warn"
if_then_some_else_none = "warn"
implicit_clone = "warn"
inconsistent_struct_constructor = "warn"
indexing_slicing = "warn"
iter_filter_is_ok = "warn"
iter_filter_is_some = "warn"
iter_not_returning_iterator = "warn"
manual_is_variant_and = "warn"
option_if_let_else = "warn"
option_option = "warn"
[profile.release]
strip = true # Automatically strip symbols from the binary.
salvo = {version = "0.58.3", features = ["logging", "affix"]}
serde = {version = "1.0.192", features = ["derive"]}
serde_json = "1.0.108"
sha256 = "1.4.0"
tokio = {version = "1.34.0", features = ["macros", "rt-multi-thread", "signal"]}

View file

@ -1,30 +0,0 @@
# This justfile is for the contrbutors of this project, not for the end user.
#
# Requirements for this justfile:
# - Linux distribution
# - just (Of course) <https://github.com/casey/just>
# - cargo (For the build and tests) <https://doc.rust-lang.org/cargo/getting-started/installation.html>
set shell := ["/usr/bin/bash", "-c"]
JUST_EXECUTABLE := "just -u -f " + justfile()
header := "Available tasks:\n"
# Get the MSRV from the Cargo.toml
msrv := `cat Cargo.toml | grep "rust-version" | sed 's/.*"\(.*\)".*/\1/'`
_default:
@{{JUST_EXECUTABLE}} --list-heading "{{header}}" --list
# Run the CI
@ci: && msrv
cargo build -q
cargo fmt -- --check
cargo clippy -- -D warnings
# Check that the current MSRV is correct
@msrv:
rustup toolchain install {{msrv}}
echo "Checking MSRV ({{msrv}})"
cargo +{{msrv}} check -q
echo "MSRV is correct"

View file

@ -1,112 +0,0 @@
[changelog]
# changelog header
header = """
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n
"""
body = """
{# Check if there is a `BREAKING-CHANGE` footer in the message or not #}\
{% macro is_breaking(commit) %}\
{{"BREAKING-CHANGE" in commit.message}}\
{% endmacro is_breaking %}\
{# Return the commit header #}\
{% macro commit_header(commit) %}\
{{commit.message | split(pat="\n") | nth(n=0) | upper_first }}\
{% endmacro commit_header %}\
{# Return the `BREAKING-CHANGE` footer message #}\
{% macro bc_des(commit) %}\
{% set lines = [] %}\
{% set found_breaking = false %}\
{% for line in commit.message | split(pat="\n") %}\
{% if found_breaking and line is not containing(":") %}\
{% set_global lines = lines | concat(with=line) %}\
{% elif found_breaking and line is containing(":") %}\
{% set_global found_breaking = false %}\
{% endif %}\
{% if line is starting_with("BREAKING-CHANGE") %}\
{% set_global found_breaking = true %}\
{% set breaking_line = line | split(pat=":") | nth(n=1) %}\
{% set_global lines = lines | concat(with=breaking_line) %}\
{% endif %}\
{% endfor %}\
{% if lines | length != 0 %}\
{{ lines | join(sep="\n") | trim_end(pat="\n") }}\
{% endif %}\
{% endmacro bc_des %}\
{% if version %}\
{% if previous.version %}\
## [{{ version | trim_start_matches(pat="v") }}](<REPO>/compare/{{ previous.version }}..{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## {{ version | trim_start_matches(pat="v") }} - {{ timestamp | date(format="%Y-%m-%d") }}
{% endif %}\
{% else %}\
## unreleased
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}\
### {{ group | upper_first }}
{% for commit in commits | sort(attribute="message") %}\
- {{ self::commit_header(commit=commit) }} ([`{{ commit.id | truncate(length=7, end="") }}`](<REPO>/commit/{{ commit.id }}))
{% if self::is_breaking(commit=commit) == "true" %}\
\t- **BC**: {{self::bc_des(commit=commit)}}
{% endif %}\
{% endfor %}\
{% endfor %}\n
"""
# remove the leading and trailing whitespace from the template
trim = true
# changelog footer
footer = """
This changelog was generated by [git-cliff](https://github.com/orhun/git-cliff)
"""
# postprocessors
postprocessors = [
{pattern = '<REPO>', replace = "https://git.4rs.nl/awiteb/telepingbot"}, # replace repository URL
{pattern = '- (\w+)(\(\w+\))?:', replace = "- "}, # Remove the type
{pattern = '- \((\w+)\):', replace = "- (**$1**)"}, # Make the scope blod
{pattern = "\t", replace = " "}, # Replace tap with 4 spaces
]
[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = false
# filter out the commits that are not conventional
filter_unconventional = true
# process each line of a commit as an individual commit
split_commits = false
# regex for preprocessing the commit messages
commit_preprocessors = [
{pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([**#${2}**](<REPO>/issues/${2}))"}, # replace issue numbers (Note the PR is also an issue in Forgejo, so this will also link to PRs)
{pattern = ' +$', replace = ""}, # Remove trailing whitespace.
{pattern = ' +', replace = " "}, # Replace multiple spaces with a single space.
]
# regex for parsing and grouping commits
commit_parsers = [
{message = "^feat", group = "Added"},
{message = "^fix", group = "Fixed"},
{message = "^(refactor|change)", group = "Changed"},
{message = "^deprecate", group = "Deprecated"},
{message = "^remove", group = "Removed"},
{message = "^security", group = "Security"},
]
# protect breaking changes from being skipped due to matching a skipping commit_parser
protect_breaking_commits = false
# filter out the commits that are not matched by commit parsers
filter_commits = false
# regex for matching git tags
tag_pattern = "v[0-9]+\\.[0-9]+\\.[0-9]+"
# regex for skipping tags
skip_tags = ""
# regex for ignoring tags
ignore_tags = "v[0-9]+\\.[0-9]+\\.[0-9]+-(alpha|beta|rc)(\\.[0-9]+)?"
# sort the tags topologically
topo_order = false
# sort the commits inside sections by oldest/newest order
sort_commits = "oldest"

View file

@ -1,13 +0,0 @@
[toolchain]
# We use nightly in development only, the project will always be compliant with
# the latest stable release and the MSRV as defined in `Cargo.toml` file.
channel = "nightly-2024-05-25"
components = [
"rustc",
"cargo",
"rust-std",
"rust-src",
"rustfmt",
"rust-analyzer",
"clippy",
]

View file

@ -1,22 +0,0 @@
unstable_features = true
version = "Two"
blank_lines_upper_bound = 2
combine_control_expr = false
wrap_comments = true
condense_wildcard_suffixes = true
edition = "2021"
enum_discrim_align_threshold = 20
force_multiline_blocks = true
format_code_in_doc_comments = true
format_generated_files = false
format_macro_matchers = true
format_strings = true
imports_layout = "HorizontalVertical"
newline_style = "Unix"
normalize_comments = true
reorder_impl_items = true
group_imports = "StdExternalCrate"
single_line_let_else_max_width = 0
struct_field_align_threshold = 20
use_try_shorthand = true

View file

@ -1,5 +1,5 @@
// A simple API to ping telegram bots and returns if it's online or not.
// Copyright (C) 2023-2024 Awiteb <a@4rs.nl>
// Copyright (C) 2023 Awiteb <awitb@hotmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
@ -8,32 +8,32 @@
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/agpl-3.0>.
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use std::sync::Arc;
use salvo::{catcher::Catcher, http::HeaderValue, hyper::header, logging::Logger, prelude::*};
use crate::{superbot, PingList};
use crate::PingList;
#[derive(Debug)]
pub(crate) struct AppState {
/// Clean text bot usernames
pub bots: Vec<String>,
pub bots: Vec<String>,
/// Sha256 tokens
pub tokens: Vec<String>,
/// The telegram clinet
tg_client: grammers_client::Client,
tg_client: grammers_client::Client,
}
#[derive(serde::Serialize)]
struct MessageSchema<'a> {
message: &'a str,
status: bool,
message: &'a str,
status: bool,
#[serde(skip)]
status_code: StatusCode,
}
@ -46,11 +46,11 @@ impl AppState {
client: grammers_client::Client,
) -> Self {
Self {
bots: bots
bots: bots
.into_iter()
.map(|b| b.trim_start_matches('@').trim().to_lowercase())
.collect(),
tokens: tokens
tokens: tokens
.into_iter()
.map(|t| sha256::digest(t.trim()))
.collect(),
@ -61,7 +61,7 @@ impl AppState {
impl<'a> MessageSchema<'a> {
/// Create new [`Message`] instance with `200 OK` status
const fn new(message: &'a str) -> Self {
fn new(message: &'a str) -> Self {
Self {
message,
status: true,
@ -78,23 +78,20 @@ impl<'a> MessageSchema<'a> {
}
fn write_json_body(res: &mut Response, json_body: impl serde::Serialize) {
res.write_body(serde_json::to_string(&json_body).expect("This should not fail"))
res.write_body(serde_json::to_string(&json_body).unwrap())
.ok();
}
#[handler]
async fn ping(req: &Request, res: &mut Response, depot: &mut Depot) {
let bot_username = req
.param::<String>("bot_username")
.expect("The path param is required");
let app_state = depot
.obtain::<Arc<AppState>>()
.expect("The app state is injected");
let bot_username = req.param::<String>("bot_username").unwrap().to_lowercase();
let app_state = depot.obtain::<Arc<AppState>>().unwrap();
let msg = if !app_state.bots.contains(&bot_username) {
MessageSchema::new("Is not authorized to check the status of this bot")
.code(StatusCode::BAD_REQUEST)
} else if let Ok(telegram_id) = superbot::send_start(&app_state.tg_client, &bot_username).await
} else if let Ok(telegram_id) =
crate::superbot::send_start(&app_state.tg_client, &bot_username).await
{
if crate::PINGED_BOTS.check(telegram_id) {
MessageSchema::new("Alive")
@ -110,7 +107,7 @@ async fn ping(req: &Request, res: &mut Response, depot: &mut Depot) {
#[handler]
async fn handle404(res: &mut Response, ctrl: &mut FlowCtrl) {
if res.status_code == Some(StatusCode::NOT_FOUND) {
if let Some(StatusCode::NOT_FOUND) = res.status_code {
write_json_body(
res,
MessageSchema::new("Not Found").code(StatusCode::NOT_FOUND),
@ -132,9 +129,7 @@ async fn handle_server_errors(res: &mut Response, ctrl: &mut FlowCtrl) {
#[handler]
async fn auth(req: &Request, res: &mut Response, depot: &mut Depot, ctrl: &mut FlowCtrl) {
let app_state = depot
.obtain::<Arc<AppState>>()
.expect("The app state is injected");
let app_state = depot.obtain::<Arc<AppState>>().unwrap();
log::info!("New auth request");
if let Some(token) = req.headers().get("Authorization") {
if let Ok(token) = token.to_str() {

View file

@ -1,5 +1,5 @@
// A simple API to ping telegram bots and returns if it's online or not.
// Copyright (C) 2023-2024 Awiteb <a@4rs.nl>
// Copyright (C) 2023 Awiteb <awitb@hotmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
@ -8,18 +8,16 @@
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/agpl-3.0>.
#![doc = include_str!("../README.md")]
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use std::{env, fs, sync::Mutex};
use lazy_static::lazy_static;
use salvo::{conn::TcpListener, Listener};
use salvo::Listener;
mod api;
mod superbot;
@ -27,7 +25,7 @@ mod superbot;
#[derive(Default, Clone)]
pub(crate) struct PingedBot {
telegram_id: u64,
ping_in: i64,
ping_in: i64,
is_response: bool,
}
@ -42,9 +40,7 @@ impl PingList for Mutex<Vec<PingedBot>> {
fn clear_outdead(&self) {
log::info!("Clear the dead pings");
let dead_time = chrono::Utc::now().timestamp() - 60;
let mut bots = self
.lock()
.expect("Another holder paniced while holding the lock");
let mut bots = self.lock().unwrap();
*bots = bots
.iter()
.filter(|b| b.ping_in > dead_time)
@ -54,9 +50,7 @@ impl PingList for Mutex<Vec<PingedBot>> {
fn add_new(&self, telegram_id: u64) {
log::debug!("Adding new bot to the list: {telegram_id}");
self.lock()
.expect("Another holder paniced while holding the lock")
.push(PingedBot::new(telegram_id));
self.lock().unwrap().push(PingedBot::new(telegram_id));
}
fn check(&self, telegram_id: u64) -> bool {
@ -64,18 +58,15 @@ impl PingList for Mutex<Vec<PingedBot>> {
self.clear_outdead();
let result = self
.lock()
.expect("Another holder paniced while holding the lock")
.unwrap()
.iter()
.any(|b| b.telegram_id == telegram_id && b.is_response);
log::debug!("Response status: {result}");
result
}
fn new_res(&self, telegram_id: u64) {
log::debug!("New res from: {telegram_id}");
let mut bots = self
.lock()
.expect("Another holder paniced while holding the lock");
let mut bots = self.lock().unwrap();
*bots = bots
.iter()
.cloned()
@ -100,13 +91,12 @@ impl PingedBot {
}
}
pub(crate) const fn new_res(mut self) -> Self {
pub(crate) fn new_res(mut self) -> Self {
self.is_response = true;
self
}
}
#[allow(clippy::absolute_paths)]
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
lazy_static! {
@ -156,11 +146,21 @@ async fn main() -> Result<()> {
let app_state = api::AppState::new(bots, tokens, client.clone());
let handler_client = client.clone();
let acceptor = TcpListener::new(format!("{host}:{port}")).bind().await;
let acceptor = salvo::conn::TcpListener::new(format!("{host}:{port}"))
.bind()
.await;
let client_handler = tokio::spawn(async move { superbot::handler(handler_client).await });
let server_handler = tokio::spawn(async move {
salvo::Server::new(acceptor)
.serve(api::service(app_state))
.serve_with_graceful_shutdown(
api::service(app_state),
async {
tokio::signal::ctrl_c()
.await
.expect("Faild to listen to ctrl_c event");
},
None,
)
.await
});

View file

@ -1,5 +1,5 @@
// A simple API to ping telegram bots and returns if it's online or not.
// Copyright (C) 2023-2024 Awiteb <a@4rs.nl>
// Copyright (C) 2023 Awiteb <awitb@hotmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
@ -8,15 +8,14 @@
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/agpl-3.0>.
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use grammers_client::{Client, Config, InitParams, SignInError, Update};
use grammers_session::Session;
use tokio::{signal, time};
use crate::PingList;
@ -35,7 +34,7 @@ pub(crate) async fn login(api_hash: String, api_id: i32) -> crate::Result<(Clien
if !client.is_authorized().await? {
println!("Signing in...");
let phone: String = promptly::prompt("Enter your phone number (international format)")?;
let token = client.request_login_code(&phone).await?;
let token = client.request_login_code(&phone, api_id, &api_hash).await?;
let code: String = promptly::prompt("Enter the code you received")?;
let signed_in = client.sign_in(&token, &code).await;
match signed_in {
@ -48,7 +47,7 @@ pub(crate) async fn login(api_hash: String, api_id: i32) -> crate::Result<(Clien
.await?;
}
Ok(_) => (),
Err(e) => return Err(e.into()),
Err(e) => panic!("{e}"),
}
let me = client.get_me().await?;
println!(
@ -83,7 +82,7 @@ fn update_handler(upd: Update) {
pub(crate) async fn handler(client: Client) {
loop {
tokio::select! {
_ = signal::ctrl_c() => {
_ = tokio::signal::ctrl_c() => {
break;
}
Ok(Some(update)) = client.next_update() => {
@ -102,7 +101,7 @@ pub(crate) async fn send_start(client: &Client, bot_username: &str) -> crate::Re
crate::PINGED_BOTS.add_new(telegram_id);
client.send_message(chat, "/start").await?;
// Sleep, wating the response
time::sleep(time::Duration::from_secs(2)).await;
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
Ok(telegram_id)
} else {
Err(format!("Invalid username `{bot_username}`").into())