Compare commits
9 Commits
71e0f92708
...
6d8af9b60a
| Author | SHA1 | Date |
|---|---|---|
|
|
6d8af9b60a | |
|
|
a34b4b14a2 | |
|
|
2af64fca40 | |
|
|
2b276647fa | |
|
|
0d386f095d | |
|
|
e63177a5b4 | |
|
|
68731984c1 | |
|
|
9d1c124ba2 | |
|
|
72cfe7b17b |
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteTargetsManager">
|
||||
<targets>
|
||||
<target name="rust:latest" type="docker" uuid="abc6565f-f912-434a-ae04-68ceee732c3a">
|
||||
<config>
|
||||
<option name="targetPlatform">
|
||||
<TargetPlatform />
|
||||
</option>
|
||||
<option name="buildNotPull" value="false" />
|
||||
<option name="pullImageConfig">
|
||||
<PullImageConfig>
|
||||
<option name="tagToPull" value="rust:latest" />
|
||||
</PullImageConfig>
|
||||
</option>
|
||||
</config>
|
||||
<ContributedStateBase type="RsLanguageRuntime">
|
||||
<config>
|
||||
<option name="cargoPath" value="/usr/local/cargo/bin/cargo" />
|
||||
<option name="cargoVersion" value="1.75.0 (1d8b05cdd 2023-11-20)" />
|
||||
<option name="rustcPath" value="/usr/local/cargo/bin/rustc" />
|
||||
<option name="rustcVersion" value="1.75.0 (82e1608df 2023-12-21)" />
|
||||
</config>
|
||||
</ContributedStateBase>
|
||||
</target>
|
||||
</targets>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="SqlDialectMappings">
|
||||
<file url="file://$PROJECT_DIR$/migrations/2023-09-20-230922_extend userinfo to include XP/up.sql" dialect="PostgreSQL" />
|
||||
<file url="file://$PROJECT_DIR$/migrations/2023-09-26-215927_add custom responses table/up.sql" dialect="PostgreSQL" />
|
||||
<file url="file://$PROJECT_DIR$/migrations/2023-11-20-091909_add constant values to each rank track for XP generation control/down.sql" dialect="PostgreSQL" />
|
||||
<file url="file://$PROJECT_DIR$/migrations/2023-11-20-091909_add constant values to each rank track for XP generation control/up.sql" dialect="PostgreSQL" />
|
||||
<file url="PROJECT" dialect="SQLite" />
|
||||
</component>
|
||||
</project>
|
||||
File diff suppressed because it is too large
Load Diff
15
Cargo.toml
15
Cargo.toml
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "badgey"
|
||||
version = "3.1.1"
|
||||
version = "4.0.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
@ -20,4 +20,17 @@ manifold = { git = "https://code.orbiter-radio.uk/discord/manifold.git" }
|
|||
poise = { version = "0.5.*", features = [ "cache" ] }
|
||||
rand = { version = "0.8.5", features = [ "small_rng" ] }
|
||||
regex = "1.9.5"
|
||||
rust-i18n = "3.1.2"
|
||||
tokio = { version = "1.16.1", features = ["sync", "macros", "rt-multi-thread"] }
|
||||
|
||||
[package.metadata.i18n]
|
||||
# The available locales for your application, default: ["en"].
|
||||
available-locales = ["en", "de"]
|
||||
|
||||
# The default locale, default: "en".
|
||||
default-locale = "en"
|
||||
|
||||
# Path for your translations YAML file, default: "locales".
|
||||
# This config for let `cargo i18n` command line tool know where to find your translations.
|
||||
# You must keep this path same as the one you pass to method `rust_i18n::i18n!`.
|
||||
load-path = "config/locales"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
"channels": {
|
||||
"log": 648260641626390528
|
||||
},
|
||||
"responses_file_path": "txt/responses.txt",
|
||||
"responses_file_path": "txt/responses",
|
||||
"services": {
|
||||
"weather": {
|
||||
"source_uri": "https://api.weatherapi.com/v1",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
_version: 2
|
||||
commands:
|
||||
custom_response:
|
||||
added:
|
||||
de: "Benutzerdefinierte Antwort erfolgreich hinzugefügt"
|
||||
en: "Custom response successfully added"
|
||||
error:
|
||||
de: "Benutzerdefinierte Antwort NICHT hinzugefügt, ein Fehler ist aufgetreten. Darüber sollten Sie sich wahrscheinlich bei Xyon beschweren. Der Fehler war %{error}"
|
||||
en: "Custom response NOT added, an error happened. You should probably complain to Xyon about that. The error was %{error}"
|
||||
marked_deleted:
|
||||
de: "Benutzerdefinierte Antwort mit der ID %{id} erfolgreich als gelöscht markiert."
|
||||
en: "Successfully marked custom response with ID %{response_id} as deleted."
|
||||
marked_undeleted:
|
||||
de: "Nicht gelöschte benutzerdefinierte Antwort mit der ID: %{response_id}"
|
||||
en: "Undeleted custom response with ID: %{response_id}"
|
||||
undelete_error_not_deleted:
|
||||
de: "Die benutzerdefinierte Antwort mit der ID %{response_id} kann nicht wiederhergestellt werden, da sie nicht von vornherein gelöscht wurde."
|
||||
en: "Can't undelete custom response with ID %{response_id} because it was not deleted in the first place."
|
||||
list_user:
|
||||
de: "Ich habe die folgenden benutzerdefinierten Antworten für %{user} gefunden: %{response_list}"
|
||||
en: "I found the following custom responses for %{user}: %{response_list}"
|
||||
ranks:
|
||||
track_switch:
|
||||
de: "Ich habe dich auf die %{new_track}-Leiter umgestellt. Du bist jetzt ein %{new_rank}. Ich hoffe, das hat sich gelohnt."
|
||||
en: "I have switched you onto the %{new_track} rank track. You're now a %{new_rank}. I hope this was worth it."
|
||||
failure:
|
||||
de: "Sie befinden sich bereits auf der %(rank_track)-Leiter."
|
||||
en: "You're already on the %(rank_track) rank track."
|
||||
rank_freeze:
|
||||
not_found:
|
||||
de: "Diesen Rang konnte ich nicht finden um ihn dir zu setzen. Wahrscheinlich musst Du die Karriere-Leiter wechseln, oder es existiert einfach nicht."
|
||||
en: "I couldn't find that rank as a rank I can give you. You might need to switch tracks, or it might just not exist."
|
||||
success:
|
||||
de: "Du bist nun für immer %{rank}. Viel Glück Harry!"
|
||||
en: "Okay. I've frozen your rank at %{rank}. Enjoy!"
|
||||
rank_unfreeze:
|
||||
success:
|
||||
de: "Dein Rang wurde enteist. Janeway wird das nicht erfreuen."
|
||||
en: "Okay. I've unfrozen your rank. Good luck out there."
|
||||
failure:
|
||||
de: "Dein Rang war nicht eingefroren."
|
||||
en: "Negative, your rank wasn't frozen."
|
||||
rank:
|
||||
current_rank:
|
||||
de: "Du bist derzeit %{current_rank}. Du brauchst %{next_level_xp} mehr XP, um das nächste Level zu erreichen"
|
||||
en: "You're currently %{current_rank}. You need %{next_level_xp} more XP to get to the next level"
|
||||
max_rank:
|
||||
de: "%{response}. Du bist bereits ganz oben angekommen! - Du kannst nicht weiter befördert werden!"
|
||||
en: "%{response}. There are no more ranks for you - you can't be promoted any further!"
|
||||
and_rank:
|
||||
de: "%{response} und Rang!"
|
||||
en: "%{response} and rank!"
|
||||
and_rank_different_level:
|
||||
de: "%{response} und du brauchst %{next_rank_xp} mehr, um den nächsten Rang zu erreichen. Viel Glück!"
|
||||
en: "%{response} and you need %{next_rank_xp} more to get to the next rank. Good luck!"
|
||||
|
||||
models:
|
||||
xp:
|
||||
cooldown:
|
||||
de: "Du hast eine Abklingzeit. Versuchen Sie es in %{timeuntil} Sekunden erneut."
|
||||
en: "You are on cooldown. Try again in %{timeuntil} seconds."
|
||||
unranked:
|
||||
de: ohne Rangliste
|
||||
en: unranked
|
||||
|
||||
misc:
|
||||
version_string:
|
||||
de: "Badgey Bot Version %{ver} erstellt um %{time} aus der Revision %{rev}"
|
||||
en: "Badgey Bot version %{ver} built at %{time} from revision %{rev}"
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{ pkgs ? import <nixpkgs> {}}:
|
||||
pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
openssl
|
||||
postgresql
|
||||
pkg-config
|
||||
];
|
||||
}
|
||||
|
|
@ -11,8 +11,8 @@ async fn add_custom_response(ctx: ManifoldContext<'_>, target: serenity::User, t
|
|||
let db = &ctx.data().database;
|
||||
|
||||
match CustomResponseInserter::new(trigger, response, target, ctx.author().clone()).insert(db) {
|
||||
Ok(_) => ctx.reply("Custom response successfully added").await?,
|
||||
Err(e) => ctx.reply(format!("Custom response NOT added, an error happened. You should probably complain to Xyon about that. The error was {}", e)).await?,
|
||||
Ok(_) => ctx.reply(t!("commands.custom_response.added")).await?,
|
||||
Err(e) => ctx.reply(t!("commands.custom_response.added.error", error = e)).await?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
|
@ -27,7 +27,7 @@ async fn remove_custom_response(ctx: ManifoldContext<'_>, id: i32) -> ManifoldRe
|
|||
response.deleted = Some(true);
|
||||
response.insert(db)?;
|
||||
|
||||
ctx.reply(format!("Successfully marked custom response with ID {} as deleted.", id)).await?;
|
||||
ctx.reply(t!("commands.custom_response.marked_deleted", response_id=id)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -41,9 +41,9 @@ async fn undelete_custom_response(ctx: ManifoldContext<'_>, id: i32) -> Manifold
|
|||
if let Some(_) = response.deleted {
|
||||
response.deleted = None;
|
||||
response.insert(db)?;
|
||||
ctx.reply(format!("Undeleted custom response with ID: {}", &id)).await?;
|
||||
ctx.reply(t!("commands.custom_response.marked_undeleted", response_id=id)).await?;
|
||||
} else {
|
||||
ctx.reply(format!("Can't undelete custom response with ID {} because it was not deleted in the first place.", &id)).await?;
|
||||
ctx.reply(t!("commands.custom_response.undelete_error_not_deleted", response_id=id)).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -63,7 +63,7 @@ async fn list_custom_responses_for_user(ctx: ManifoldContext<'_>, target: sereni
|
|||
answer.push_str("\nNone found");
|
||||
}
|
||||
|
||||
ctx.reply(format!("I found the following custom responses for {}: {}", &target.mention(), answer)).await?;
|
||||
ctx.reply(t!("commands.custom_response.list_user", user = &target.mention(), response_list = answer)).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@ use poise::Command;
|
|||
|
||||
pub mod custom_responses;
|
||||
pub mod ranks;
|
||||
pub mod moderation;
|
||||
|
||||
pub fn collect_commands() -> Vec<Command<ManifoldData, ManifoldError>> {
|
||||
commands().into_iter()
|
||||
.chain(custom_responses::commands())
|
||||
.chain(ranks::commands())
|
||||
.chain(moderation::commands())
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
use manifold::error::{ManifoldError, ManifoldResult};
|
||||
use manifold::{ManifoldContext, ManifoldData};
|
||||
use poise::serenity_prelude as serenity;
|
||||
|
||||
#[poise::command(slash_command, prefix_command, required_permissions = "MODERATE_MEMBERS")]
|
||||
async fn void_user(_ctx: ManifoldContext<'_>, _target: serenity::User) -> ManifoldResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[poise::command(slash_command, prefix_command, required_permissions = "MODERATE_MEMBERS")]
|
||||
async fn airlock_user(_ctx: ManifoldContext<'_>, _target: serenity::User) -> ManifoldResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[poise::command(slash_command, prefix_command, required_permissions = "MODERATE_MEMBERS")]
|
||||
async fn unvoid_user(_ctx: ManifoldContext<'_>, _target: serenity::User) -> ManifoldResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[poise::command(slash_command, prefix_command, required_permissions = "MODERATE_MEMBERS")]
|
||||
async fn record_chronicle(_ctx: ManifoldContext<'_>, _target: serenity::User) -> ManifoldResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn commands() -> [poise::Command<ManifoldData, ManifoldError>; 4] {
|
||||
[void_user(), unvoid_user(), airlock_user(), record_chronicle()]
|
||||
}
|
||||
|
|
@ -26,11 +26,11 @@ async fn switch_rank_track(ctx: ManifoldContext<'_>, #[description = "Track to s
|
|||
|
||||
xp.rank_track = parsed_track.track_id;
|
||||
|
||||
ctx.reply(format!("I have switched you onto the {} rank track. You're now a {}. I hope this was worth it.", parsed_track.track_name, new_level_rank.rank_name)).await?;
|
||||
ctx.reply(t!("commands.ranks.track_switch", new_track = parsed_track.track_name, new_rank = new_level_rank.rank_name)).await?;
|
||||
xp.rank_track_last_changed = Some(chrono::Utc::now().timestamp());
|
||||
xp.insert(db)?;
|
||||
} else {
|
||||
ctx.reply(format!("You're already on the {} rank track.", parsed_track.track_name)).await?;
|
||||
ctx.reply(t!("commands.ranks.track_switch.failure", rank_track = parsed_track.track_name)).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -51,7 +51,7 @@ async fn freeze_rank(ctx: ManifoldContext<'_>, #[rest] #[description = "Rank to
|
|||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
error!("Rank lookup error: {}", e);
|
||||
ctx.reply(format!("I couldn't find that rank as a rank I can give you. You might need to switch tracks, or it might just not exist.")).await?;
|
||||
ctx.reply(t!("commands.ranks.rank_freeze.not_found")).await?;
|
||||
Err(e)?
|
||||
}
|
||||
};
|
||||
|
|
@ -67,7 +67,7 @@ async fn freeze_rank(ctx: ManifoldContext<'_>, #[rest] #[description = "Rank to
|
|||
|
||||
if let Some(mut member) = ctx.author_member().await {
|
||||
member.to_mut().add_role(ctx, frozen_rank.role_id as u64).await?;
|
||||
ctx.reply(format!("Okay. I've frozen your rank at {}. Enjoy!", frozen_rank.rank_name)).await?;
|
||||
ctx.reply(t!("commands.ranks.rank_freeze.success", rank = frozen_rank.rank_name)).await?;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -78,9 +78,9 @@ async fn freeze_rank(ctx: ManifoldContext<'_>, #[rest] #[description = "Rank to
|
|||
}
|
||||
|
||||
xp.freeze_rank = None;
|
||||
ctx.reply(format!("Okay. I've unfrozen your rank. Good luck out there.")).await?;
|
||||
ctx.reply(t!("commands.ranks.rank_unfreeze.success")).await?;
|
||||
} else {
|
||||
ctx.reply(format!("Negative, your rank wasn't frozen.")).await?;
|
||||
ctx.reply(t!("commands.ranks.rank_unfreeze.failure")).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,13 +105,13 @@ async fn rank(ctx: ManifoldContext<'_>) -> ManifoldResult<()> {
|
|||
let next_level_xp = xp.get_xp_to_next_level(&db);
|
||||
let next_rank_xp = xp.get_xp_to_next_rank(&db).unwrap_or(0);
|
||||
|
||||
let mut response = format!("You're currently {}. You need {} more XP to get to the next level", RoleId::from(current_rank.role_id as u64).mention(), next_level_xp);
|
||||
let mut response = t!("commands.ranks.rank.current_rank", current_rank = RoleId::from(current_rank.role_id as u64).mention(), next_level_xp = next_level_xp);
|
||||
if next_rank_xp == 0 {
|
||||
response = format!("{}. There are no more ranks for you - you can't be promoted any further!", response);
|
||||
response = t!("commands.ranks.rank.max_rank", reponse = response);
|
||||
} else if next_rank_xp == next_level_xp {
|
||||
response = format!("{} and rank!", response);
|
||||
response = t!("commands.ranks.rank.and_rank", response = response);
|
||||
} else {
|
||||
response = format!("{} and you need {} more to rank up. Good luck!", response, next_rank_xp);
|
||||
response = t!("commands.ranks.rank.and_rank_different_level", response = response, next_rank_xp = next_rank_xp);
|
||||
}
|
||||
|
||||
ctx.reply(response).await?;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use built::chrono;
|
||||
use manifold::error::{ManifoldError, ManifoldResult};
|
||||
use manifold::events::{Handler, EventHandler};
|
||||
use manifold::events::EventHandler;
|
||||
use manifold::ManifoldData;
|
||||
use poise::{async_trait, FrameworkContext, Event};
|
||||
use poise::serenity_prelude::{Context, Mentionable, Message, RoleId};
|
||||
|
|
@ -18,8 +18,6 @@ pub struct BadgeyHandler {
|
|||
#[async_trait]
|
||||
impl EventHandler for BadgeyHandler {
|
||||
async fn listen(ctx: &Context, framework_ctx: FrameworkContext<'_, ManifoldData, ManifoldError>, event: &Event<'_>) -> ManifoldResult<()> {
|
||||
Handler::listen(ctx, framework_ctx, event).await?;
|
||||
|
||||
match event {
|
||||
Event::Message { new_message } => BadgeyHandler::message(&ctx, &framework_ctx, new_message).await,
|
||||
_ => Ok(())
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@ pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations");
|
|||
|
||||
#[tokio::main]
|
||||
pub async fn run(arguments: ArgMatches) {
|
||||
rust_i18n::set_locale(arguments.get_one::<String>("locale").unwrap());
|
||||
|
||||
let git_info: String = built_info::GIT_VERSION.unwrap_or("unknown").to_string();
|
||||
let version_string = format!("Badgey Bot version {ver} built at {time} from revision {rev}", ver=built_info::PKG_VERSION, time=built_info::BUILT_TIME_UTC, rev=git_info);
|
||||
let version_string = t!("misc.version_string", ver=built_info::PKG_VERSION, time=built_info::BUILT_TIME_UTC, rev=git_info).to_string();
|
||||
|
||||
let client = match manifold::prepare_client::<BadgeyHandler>(arguments, GatewayIntents::all(), commands::collect_commands(), version_string, MIGRATIONS).await {
|
||||
Ok(c) => c,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
use built::chrono::{NaiveDateTime, Utc};
|
||||
use built::chrono::{DateTime, Utc};
|
||||
use diesel::prelude::*;
|
||||
use diesel::{insert_into, sql_function};
|
||||
use diesel::insert_into;
|
||||
use regex::Regex;
|
||||
use poise::serenity_prelude as serenity;
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ use manifold::error::{ManifoldError, ManifoldResult};
|
|||
use manifold::models::user::UserInfo;
|
||||
use manifold::schema::userinfo;
|
||||
|
||||
sql_function!(fn random() -> Text);
|
||||
define_sql_function!(fn random() -> Text);
|
||||
|
||||
use crate::badgey::schema::*;
|
||||
|
||||
|
|
@ -112,6 +112,6 @@ impl CustomResponse {
|
|||
|
||||
impl Display for CustomResponse {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "ID: {}, trigger: {}, response: {}, added by: {}, added on: {}, deleted: {}", self.id, self.trigger, self.response, serenity::UserId::from(self.added_by as u64), NaiveDateTime::from_timestamp_opt(self.added_on, 0).unwrap(), self.deleted.unwrap_or(false))
|
||||
write!(f, "ID: {}, trigger: {}, response: {}, added by: {}, added on: {}, deleted: {}", self.id, self.trigger, self.response, serenity::UserId::from(self.added_by as u64), DateTime::from_timestamp(self.added_on, 0).unwrap(), self.deleted.unwrap_or(false))
|
||||
}
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ impl Xp {
|
|||
if let Some(v) = value {
|
||||
if v > &(chrono::Utc::now().timestamp() - timeout) {
|
||||
let timeuntil = v - (chrono::Utc::now().timestamp() - timeout);
|
||||
Err(format!("You are on cooldown. Try again in {} seconds.", timeuntil))?;
|
||||
Err(t!("models.xp.cooldown", timeuntil = timeuntil))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ impl Rank {
|
|||
role_id: 0,
|
||||
required_level: 0,
|
||||
rank_track: 0,
|
||||
rank_name: "unranked".to_string(),
|
||||
rank_name: t!("models.xp.unranked").to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate rust_i18n;
|
||||
|
||||
pub mod badgey;
|
||||
|
||||
|
|
@ -9,6 +10,8 @@ pub mod built_info {
|
|||
include!(concat!(env!("OUT_DIR"), "/built.rs"));
|
||||
}
|
||||
|
||||
i18n!("config/locales");
|
||||
|
||||
fn main() {
|
||||
|
||||
env_logger::init();
|
||||
|
|
@ -33,6 +36,10 @@ fn main() {
|
|||
.value_name("ENV")
|
||||
.default_value("Production")
|
||||
.help("Bot environment to use. Determines which config settings are read. Defaults to Production."))
|
||||
.arg(Arg::new("locale")
|
||||
.short('l')
|
||||
.default_value("en")
|
||||
.help("Bot locale to run in, en and de currently supported"))
|
||||
.arg(Arg::new("make-config")
|
||||
.short('M')
|
||||
.long("make-config")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
[bot startup]
|
||||
**B A D G E Y** Programminitialisierung. Laden von Zielen aus dem Speicher.
|
||||
Badgey lebt wieder! Nichts kann Badgey erlegen! Badgey ist unzerstörbar!
|
||||
Retikulierende Splines....
|
||||
[help footer]
|
||||
Badgey möchte, dass du weißt, dass er nichts als Liebe für dich empfindet. Noch.
|
||||
Badgeys geduld ist grenzenlos! Er wünscht Ihnen nichts als viel Glück auf Ihrer Entdeckungsreise.
|
||||
Badgey möchte wissen, warum du nach seinen Daten fragst.
|
||||
Badgey hat diese Anfrage über seine innersten Strukturen aufgezeichnet. Badgey wird sich erinnern.
|
||||
Badgey weiß, wo du schläfst, weißt du. Er wollte nur, dass du dich daran erinnerst.
|
||||
[weather card footer]
|
||||
Badgey Weather wurde Ihnen in Zusammenarbeit mit AstroGlide für den reibungslosesten Betrieb zur Verfügung gestellt, den Sie jemals durchführen werden.This weather broadcast and all which preceded it are entirely fictional. Badgey takes no responsibility for any harm caused by believing otherwise.
|
||||
Badgey Weather, stolz angetrieben von einem Rasenmähermotor und einem 93-jährigen Veteranen, der einfach nicht aufgeben will.
|
||||
Der Badgey Weather Service arbeitet mit Ihren Spenden und den Tränen der Faschisten.
|
||||
Wetter von Badgey. Nicht die Berichterstattung. Das tatsächliche Wetter. Ich kann tun, was ich will.3
|
||||
Dieser Bericht wird sich innerhalb von 5 sekunden selbst zerstören.
|
||||
Alle im obigen Wetterbericht enthaltenen Informationen sind nicht für den menschlichen Verzehr geeignet. Bei Kontakt mit den Augen konsultieren Sie bitte einen Arzt.
|
||||
Ich glaube, Ihr Warpkern ist undicht.
|
||||
Badgey versuchte, diesen Wetterbericht von der Sternenflotte absegnen zu lassen, aber die Sternenflotte leugnet jede Kenntnis von der Existenz von Badgey, was Badgey traurig machte.
|
||||
[end]
|
||||
Loading…
Reference in New Issue