diff --git a/src/EllieBot/Migrations/PostgreSql/20250323021916_linkfixer.sql b/src/EllieBot/Migrations/PostgreSql/20250323021916_linkfixer.sql
new file mode 100644
index 0000000..01bd6b3
--- /dev/null
+++ b/src/EllieBot/Migrations/PostgreSql/20250323021916_linkfixer.sql
@@ -0,0 +1,16 @@
+START TRANSACTION;
+CREATE TABLE linkfix (
+    id integer GENERATED BY DEFAULT AS IDENTITY,
+    guildid numeric(20,0) NOT NULL,
+    olddomain text NOT NULL,
+    newdomain text NOT NULL,
+    CONSTRAINT pk_linkfix PRIMARY KEY (id)
+);
+
+CREATE UNIQUE INDEX ix_linkfix_guildid_olddomain ON linkfix (guildid, olddomain);
+
+INSERT INTO "__EFMigrationsHistory" (migrationid, productversion)
+VALUES ('20250323021916_linkfixer', '9.0.1');
+
+COMMIT;
+
diff --git a/src/EllieBot/Migrations/PostgreSql/20250319010930_init.Designer.cs b/src/EllieBot/Migrations/PostgreSql/20250323022235_init.Designer.cs
similarity index 99%
rename from src/EllieBot/Migrations/PostgreSql/20250319010930_init.Designer.cs
rename to src/EllieBot/Migrations/PostgreSql/20250323022235_init.Designer.cs
index 6b6214f..45a075b 100644
--- a/src/EllieBot/Migrations/PostgreSql/20250319010930_init.Designer.cs
+++ b/src/EllieBot/Migrations/PostgreSql/20250323022235_init.Designer.cs
@@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
 namespace EllieBot.Migrations.PostgreSql
 {
     [DbContext(typeof(PostgreSqlContext))]
-    [Migration("20250319010930_init")]
+    [Migration("20250323022235_init")]
     partial class init
     {
         /// <inheritdoc />
@@ -1541,6 +1541,39 @@ namespace EllieBot.Migrations.PostgreSql
                     b.ToTable("imageonlychannels", (string)null);
                 });
 
+            modelBuilder.Entity("EllieBot.Db.Models.LinkFix", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasColumnName("id");
+
+                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
+
+                    b.Property<decimal>("GuildId")
+                        .HasColumnType("numeric(20,0)")
+                        .HasColumnName("guildid");
+
+                    b.Property<string>("NewDomain")
+                        .IsRequired()
+                        .HasColumnType("text")
+                        .HasColumnName("newdomain");
+
+                    b.Property<string>("OldDomain")
+                        .IsRequired()
+                        .HasColumnType("text")
+                        .HasColumnName("olddomain");
+
+                    b.HasKey("Id")
+                        .HasName("pk_linkfix");
+
+                    b.HasIndex("GuildId", "OldDomain")
+                        .IsUnique()
+                        .HasDatabaseName("ix_linkfix_guildid_olddomain");
+
+                    b.ToTable("linkfix", (string)null);
+                });
+
             modelBuilder.Entity("EllieBot.Db.Models.LiveChannelConfig", b =>
                 {
                     b.Property<int>("Id")
diff --git a/src/EllieBot/Migrations/PostgreSql/20250319010930_init.cs b/src/EllieBot/Migrations/PostgreSql/20250323022235_init.cs
similarity index 99%
rename from src/EllieBot/Migrations/PostgreSql/20250319010930_init.cs
rename to src/EllieBot/Migrations/PostgreSql/20250323022235_init.cs
index 6cfd21e..8ec83bd 100644
--- a/src/EllieBot/Migrations/PostgreSql/20250319010930_init.cs
+++ b/src/EllieBot/Migrations/PostgreSql/20250323022235_init.cs
@@ -550,6 +550,21 @@ namespace EllieBot.Migrations.PostgreSql
                     table.PrimaryKey("pk_imageonlychannels", x => x.id);
                 });
 
+            migrationBuilder.CreateTable(
+                name: "linkfix",
+                columns: table => new
+                {
+                    id = table.Column<int>(type: "integer", nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
+                    olddomain = table.Column<string>(type: "text", nullable: false),
+                    newdomain = table.Column<string>(type: "text", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("pk_linkfix", x => x.id);
+                });
+
             migrationBuilder.CreateTable(
                 name: "livechannelconfig",
                 columns: table => new
@@ -1999,6 +2014,12 @@ namespace EllieBot.Migrations.PostgreSql
                 column: "channelid",
                 unique: true);
 
+            migrationBuilder.CreateIndex(
+                name: "ix_linkfix_guildid_olddomain",
+                table: "linkfix",
+                columns: new[] { "guildid", "olddomain" },
+                unique: true);
+
             migrationBuilder.CreateIndex(
                 name: "ix_livechannelconfig_guildid",
                 table: "livechannelconfig",
@@ -2501,6 +2522,9 @@ namespace EllieBot.Migrations.PostgreSql
             migrationBuilder.DropTable(
                 name: "imageonlychannels");
 
+            migrationBuilder.DropTable(
+                name: "linkfix");
+
             migrationBuilder.DropTable(
                 name: "livechannelconfig");
 
diff --git a/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs b/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs
index 0c236ba..f8ed231 100644
--- a/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs
+++ b/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs
@@ -1538,6 +1538,39 @@ namespace EllieBot.Migrations.PostgreSql
                     b.ToTable("imageonlychannels", (string)null);
                 });
 
+            modelBuilder.Entity("EllieBot.Db.Models.LinkFix", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasColumnName("id");
+
+                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
+
+                    b.Property<decimal>("GuildId")
+                        .HasColumnType("numeric(20,0)")
+                        .HasColumnName("guildid");
+
+                    b.Property<string>("NewDomain")
+                        .IsRequired()
+                        .HasColumnType("text")
+                        .HasColumnName("newdomain");
+
+                    b.Property<string>("OldDomain")
+                        .IsRequired()
+                        .HasColumnType("text")
+                        .HasColumnName("olddomain");
+
+                    b.HasKey("Id")
+                        .HasName("pk_linkfix");
+
+                    b.HasIndex("GuildId", "OldDomain")
+                        .IsUnique()
+                        .HasDatabaseName("ix_linkfix_guildid_olddomain");
+
+                    b.ToTable("linkfix", (string)null);
+                });
+
             modelBuilder.Entity("EllieBot.Db.Models.LiveChannelConfig", b =>
                 {
                     b.Property<int>("Id")
diff --git a/src/EllieBot/Migrations/Sqlite/20250323021857_linkfixer.sql b/src/EllieBot/Migrations/Sqlite/20250323021857_linkfixer.sql
new file mode 100644
index 0000000..deb0149
--- /dev/null
+++ b/src/EllieBot/Migrations/Sqlite/20250323021857_linkfixer.sql
@@ -0,0 +1,15 @@
+BEGIN TRANSACTION;
+CREATE TABLE "LinkFix" (
+    "Id" INTEGER NOT NULL CONSTRAINT "PK_LinkFix" PRIMARY KEY AUTOINCREMENT,
+    "GuildId" INTEGER NOT NULL,
+    "OldDomain" TEXT NOT NULL,
+    "NewDomain" TEXT NOT NULL
+);
+
+CREATE UNIQUE INDEX "IX_LinkFix_GuildId_OldDomain" ON "LinkFix" ("GuildId", "OldDomain");
+
+INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
+VALUES ('20250323021857_linkfixer', '9.0.1');
+
+COMMIT;
+
diff --git a/src/EllieBot/Migrations/Sqlite/20250319010920_init.Designer.cs b/src/EllieBot/Migrations/Sqlite/20250323022218_init.Designer.cs
similarity index 99%
rename from src/EllieBot/Migrations/Sqlite/20250319010920_init.Designer.cs
rename to src/EllieBot/Migrations/Sqlite/20250323022218_init.Designer.cs
index fc2c559..799caba 100644
--- a/src/EllieBot/Migrations/Sqlite/20250319010920_init.Designer.cs
+++ b/src/EllieBot/Migrations/Sqlite/20250323022218_init.Designer.cs
@@ -11,7 +11,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
 namespace EllieBot.Migrations.Sqlite
 {
     [DbContext(typeof(SqliteContext))]
-    [Migration("20250319010920_init")]
+    [Migration("20250323022218_init")]
     partial class init
     {
         /// <inheritdoc />
@@ -1151,6 +1151,31 @@ namespace EllieBot.Migrations.Sqlite
                     b.ToTable("ImageOnlyChannels");
                 });
 
+            modelBuilder.Entity("EllieBot.Db.Models.LinkFix", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("INTEGER");
+
+                    b.Property<ulong>("GuildId")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<string>("NewDomain")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("OldDomain")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("GuildId", "OldDomain")
+                        .IsUnique();
+
+                    b.ToTable("LinkFix");
+                });
+
             modelBuilder.Entity("EllieBot.Db.Models.LiveChannelConfig", b =>
                 {
                     b.Property<int>("Id")
diff --git a/src/EllieBot/Migrations/Sqlite/20250319010920_init.cs b/src/EllieBot/Migrations/Sqlite/20250323022218_init.cs
similarity index 99%
rename from src/EllieBot/Migrations/Sqlite/20250319010920_init.cs
rename to src/EllieBot/Migrations/Sqlite/20250323022218_init.cs
index 7089818..a3e5477 100644
--- a/src/EllieBot/Migrations/Sqlite/20250319010920_init.cs
+++ b/src/EllieBot/Migrations/Sqlite/20250323022218_init.cs
@@ -550,6 +550,21 @@ namespace EllieBot.Migrations.Sqlite
                     table.PrimaryKey("PK_ImageOnlyChannels", x => x.Id);
                 });
 
+            migrationBuilder.CreateTable(
+                name: "LinkFix",
+                columns: table => new
+                {
+                    Id = table.Column<int>(type: "INTEGER", nullable: false)
+                        .Annotation("Sqlite:Autoincrement", true),
+                    GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
+                    OldDomain = table.Column<string>(type: "TEXT", nullable: false),
+                    NewDomain = table.Column<string>(type: "TEXT", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_LinkFix", x => x.Id);
+                });
+
             migrationBuilder.CreateTable(
                 name: "LiveChannelConfig",
                 columns: table => new
@@ -2001,6 +2016,12 @@ namespace EllieBot.Migrations.Sqlite
                 column: "ChannelId",
                 unique: true);
 
+            migrationBuilder.CreateIndex(
+                name: "IX_LinkFix_GuildId_OldDomain",
+                table: "LinkFix",
+                columns: new[] { "GuildId", "OldDomain" },
+                unique: true);
+
             migrationBuilder.CreateIndex(
                 name: "IX_LiveChannelConfig_GuildId",
                 table: "LiveChannelConfig",
@@ -2503,6 +2524,9 @@ namespace EllieBot.Migrations.Sqlite
             migrationBuilder.DropTable(
                 name: "ImageOnlyChannels");
 
+            migrationBuilder.DropTable(
+                name: "LinkFix");
+
             migrationBuilder.DropTable(
                 name: "LiveChannelConfig");
 
diff --git a/src/EllieBot/Migrations/Sqlite/SqliteContextModelSnapshot.cs b/src/EllieBot/Migrations/Sqlite/SqliteContextModelSnapshot.cs
index 2c146f0..c70ba74 100644
--- a/src/EllieBot/Migrations/Sqlite/SqliteContextModelSnapshot.cs
+++ b/src/EllieBot/Migrations/Sqlite/SqliteContextModelSnapshot.cs
@@ -1148,6 +1148,31 @@ namespace EllieBot.Migrations.Sqlite
                     b.ToTable("ImageOnlyChannels");
                 });
 
+            modelBuilder.Entity("EllieBot.Db.Models.LinkFix", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("INTEGER");
+
+                    b.Property<ulong>("GuildId")
+                        .HasColumnType("INTEGER");
+
+                    b.Property<string>("NewDomain")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.Property<string>("OldDomain")
+                        .IsRequired()
+                        .HasColumnType("TEXT");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("GuildId", "OldDomain")
+                        .IsUnique();
+
+                    b.ToTable("LinkFix");
+                });
+
             modelBuilder.Entity("EllieBot.Db.Models.LiveChannelConfig", b =>
                 {
                     b.Property<int>("Id")
diff --git a/src/EllieBot/Modules/Utility/LinkFixer/LinkFix.cs b/src/EllieBot/Modules/Utility/LinkFixer/LinkFix.cs
new file mode 100644
index 0000000..b1dd35a
--- /dev/null
+++ b/src/EllieBot/Modules/Utility/LinkFixer/LinkFix.cs
@@ -0,0 +1,40 @@
+using System.ComponentModel.DataAnnotations;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+
+namespace EllieBot.Db.Models;
+
+/// <summary>
+/// Represents a link fix configuration for a guild
+/// </summary>
+public class LinkFix
+{
+    [Key]
+    public int Id { get; set; }
+
+    /// <summary>
+    /// ID of the guild this link fix belongs to
+    /// </summary>
+    public ulong GuildId { get; set; }
+    
+    /// <summary>
+    /// The domain to be replaced
+    /// </summary>
+    public string OldDomain { get; set; } = null!;
+    
+    /// <summary>
+    /// The domain to replace with
+    /// </summary>
+    public string NewDomain { get; set; } = null!;
+}
+
+/// <summary>
+/// Entity configuration for <see cref="LinkFix"/>
+/// </summary>
+public class LinkFixConfiguration : IEntityTypeConfiguration<LinkFix>
+{
+    public void Configure(EntityTypeBuilder<LinkFix> builder)
+    {
+        builder.HasIndex(x => new { x.GuildId, x.OldDomain }).IsUnique();
+    }
+}
\ No newline at end of file
diff --git a/src/EllieBot/Modules/Utility/LinkFixer/LinkFixerCommands.cs b/src/EllieBot/Modules/Utility/LinkFixer/LinkFixerCommands.cs
new file mode 100644
index 0000000..11c57af
--- /dev/null
+++ b/src/EllieBot/Modules/Utility/LinkFixer/LinkFixerCommands.cs
@@ -0,0 +1,100 @@
+using DryIoc.ImTools;
+using EllieBot.Modules.Utility.LinkFixer;
+
+namespace EllieBot.Modules.Utility;
+
+public partial class Utility
+{
+    [Group]
+    public class LinkFixerCommands : EllieModule<LinkFixerService>
+    {
+        [Cmd]
+        [RequireContext(ContextType.Guild)]
+        [UserPerm(GuildPerm.ManageMessages)]
+        public async Task LinkFix(string oldDomain, string? newDomain = null)
+        {
+            if (string.IsNullOrWhiteSpace(newDomain))
+            {
+                var rmSuccess = await _service.RemoveLinkFixAsync(ctx.Guild.Id, oldDomain);
+
+                if (rmSuccess)
+                    await Response().Confirm(strs.linkfix_removed(Format.Bold(oldDomain))).SendAsync();
+                else
+                    await Response().Error(strs.linkfix_not_found(Format.Bold(oldDomain))).SendAsync();
+
+                return;
+            }
+
+            oldDomain = CleanDomain(oldDomain);
+            newDomain = newDomain.Trim();
+
+            if (string.IsNullOrWhiteSpace(oldDomain) || string.IsNullOrWhiteSpace(newDomain))
+            {
+                await Response().Error(strs.linkfix_invalid_domains).SendAsync();
+                return;
+            }
+
+            var success = await _service.AddLinkFixAsync(ctx.Guild.Id, oldDomain, newDomain);
+            if (success)
+                await Response().Confirm(strs.linkfix_added(Format.Bold(oldDomain), Format.Bold(newDomain))).SendAsync();
+            else
+                await Response().Error(strs.linkfix_already_exists(Format.Bold(oldDomain))).SendAsync();
+        }
+
+        [Cmd]
+        [RequireContext(ContextType.Guild)]
+        public async Task LinkFixList()
+        {
+            var linkFixes = _service.GetLinkFixes(ctx.Guild.Id);
+            if (linkFixes.Count == 0)
+            {
+                await Response().Confirm(strs.linkfix_list_none).SendAsync();
+                return;
+            }
+
+            var items = linkFixes.Select(x => $"{Format.Bold(x.Key)} -> {Format.Bold(x.Value)}").ToList();
+
+            await Response()
+                .Paginated()
+                .Items(items)
+                .PageSize(10)
+                .Page((items, _) =>
+                {
+                    var eb = CreateEmbed()
+                        .WithTitle(GetText(strs.linkfix_list_title))
+                        .WithDescription(string.Join('\n', items))
+                        .WithOkColor();
+
+                    return eb;
+                })
+                .SendAsync();
+        }
+
+        /// <summary>
+        /// Removes protocol and www. from a domain
+        /// </summary>
+        /// <param name="domain">The domain to clean</param>
+        private static string CleanDomain(string domain)
+        {
+            // Remove protocol if present
+            if (domain.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
+                domain = domain[7..];
+            else if (domain.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
+                domain = domain[8..];
+
+            // Remove www. if present
+            if (domain.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
+                domain = domain[4..];
+
+            // Remove any path or query string
+            var pathIndex = domain.IndexOf('/');
+            if (pathIndex > 0)
+                domain = domain[..pathIndex];
+
+            if (domain.Split('.').Length != 2)
+                return string.Empty;
+
+            return domain.ToLowerInvariant();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/EllieBot/Modules/Utility/LinkFixer/LinkFixerService.cs b/src/EllieBot/Modules/Utility/LinkFixer/LinkFixerService.cs
new file mode 100644
index 0000000..cf8ba82
--- /dev/null
+++ b/src/EllieBot/Modules/Utility/LinkFixer/LinkFixerService.cs
@@ -0,0 +1,133 @@
+using System.Text.RegularExpressions;
+using LinqToDB;
+using LinqToDB.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
+using EllieBot.Common.ModuleBehaviors;
+using EllieBot.Db.Models;
+
+namespace EllieBot.Modules.Utility.LinkFixer;
+
+/// <summary>
+/// Service for managing link fixing functionality
+/// </summary>
+public partial class LinkFixerService(DbService db) : IReadyExecutor, IExecNoCommand, IEService
+{
+    private readonly ConcurrentDictionary<ulong, ConcurrentDictionary<string, string>> _guildLinkFixes = new();
+
+    public async Task OnReadyAsync()
+    {
+        await using var uow = db.GetDbContext();
+        var linkFixes = await uow.GetTable<LinkFix>()
+            .AsNoTracking()
+            .ToListAsyncLinqToDB();
+
+        foreach (var fix in linkFixes)
+        {
+            var guildDict = _guildLinkFixes.GetOrAdd(fix.GuildId, _ => new(StringComparer.InvariantCultureIgnoreCase));
+            guildDict.TryAdd(fix.OldDomain.ToLowerInvariant(), fix.NewDomain);
+        }
+    }
+
+    public async Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
+    {
+        if(guild is null)
+        return;
+
+        var guildId = guild.Id;
+        if (!_guildLinkFixes.TryGetValue(guildId, out var guildDict))
+            return;
+
+        var content = msg.Content;
+        if (string.IsNullOrWhiteSpace(content))
+            return;
+
+        var words = content.Split(' ', StringSplitOptions.RemoveEmptyEntries);
+        foreach (var word in words)
+        {
+            var match = UrlRegex().Match(word);
+            if (!match.Success)
+                continue;
+
+            var domain = match.Groups["domain"].Value;
+            if (string.IsNullOrWhiteSpace(domain))
+                continue;
+
+            if(!guildDict.TryGetValue(domain, out var newDomain))
+                continue;
+
+            var newUrl = match.Groups["prefix"].Value + newDomain + match.Groups["suffix"].Value;
+            await msg.ReplyAsync(newUrl, allowedMentions: AllowedMentions.None);
+        }
+    }
+
+    [GeneratedRegex("(?<prefix>https?://(?:www\\.)?)(?<domain>[^/]+)(?<suffix>.*)")]
+    private partial Regex UrlRegex();
+
+    /// <summary>
+    /// Adds a new link fix for a guild
+    /// </summary>
+    /// <param name="guildId">ID of the guild</param>
+    /// <param name="oldDomain">Domain to be replaced</param>
+    /// <param name="newDomain">Domain to replace with</param>
+    /// <returns>True if successfully added, false if already exists</returns>
+    public async Task<bool> AddLinkFixAsync(ulong guildId, string oldDomain, string newDomain)
+    {
+        oldDomain = oldDomain.ToLowerInvariant();
+        
+        var guildDict = _guildLinkFixes.GetOrAdd(guildId, _ => new ConcurrentDictionary<string, string>());
+        guildDict[oldDomain] = newDomain;
+        
+        await using var uow = db.GetDbContext();
+        await uow.GetTable<LinkFix>()
+            .InsertOrUpdateAsync(() => new LinkFix
+            {
+                GuildId = guildId,
+                OldDomain = oldDomain,
+                NewDomain = newDomain
+            },
+            old => new LinkFix
+            {
+                NewDomain = newDomain
+            },
+            () => new LinkFix
+            {
+                GuildId = guildId,
+                OldDomain = oldDomain,
+            });
+
+        return true;
+    }
+
+    /// <summary>
+    /// Removes a link fix from a guild
+    /// </summary>
+    /// <param name="guildId">ID of the guild</param>
+    /// <param name="oldDomain">Domain to remove from fixes</param>
+    /// <returns>True if successfully removed, false if not found</returns>
+    public async Task<bool> RemoveLinkFixAsync(ulong guildId, string oldDomain)
+    {
+        oldDomain = oldDomain.ToLowerInvariant();
+        
+        if (!_guildLinkFixes.TryGetValue(guildId, out var guildDict) || !guildDict.TryRemove(oldDomain, out _))
+            return false;
+
+        await using var uow = db.GetDbContext();
+        await uow.GetTable<LinkFix>()
+            .DeleteAsync(lf => lf.GuildId == guildId && lf.OldDomain == oldDomain);
+
+        return true;
+    }
+
+    /// <summary>
+    /// Gets all link fixes for a guild
+    /// </summary>
+    /// <param name="guildId">ID of the guild</param>
+    /// <returns>Dictionary of old domains to new domains</returns>
+    public IReadOnlyDictionary<string, string> GetLinkFixes(ulong guildId)
+    {
+        if (_guildLinkFixes.TryGetValue(guildId, out var guildDict))
+            return guildDict;
+
+        return new Dictionary<string, string>();
+    }
+}
\ No newline at end of file
diff --git a/src/EllieBot/strings/aliases.yml b/src/EllieBot/strings/aliases.yml
index 8d02258..112c63c 100644
--- a/src/EllieBot/strings/aliases.yml
+++ b/src/EllieBot/strings/aliases.yml
@@ -1644,4 +1644,10 @@ livechlist:
 livechremove:
    - livechremove
    - lchd
-   - lchrm
\ No newline at end of file
+   - lchrm
+linkfix:
+  - linkfix
+  - lfix
+linkfixlist: 
+  - linkfixlist
+  - lfixlist
\ No newline at end of file
diff --git a/src/EllieBot/strings/commands/commands.en-US.yml b/src/EllieBot/strings/commands/commands.en-US.yml
index ddf0a6c..9eb73a1 100644
--- a/src/EllieBot/strings/commands/commands.en-US.yml
+++ b/src/EllieBot/strings/commands/commands.en-US.yml
@@ -5148,4 +5148,24 @@ livechremove:
      - '#general'
    params:
      - channel:
-         desc: "The channel to remove from live channels."
\ No newline at end of file
+         desc: "The channel to remove from live channels."
+linkfix:
+  desc: |-
+    Configures automatic link fixing from one site to another.
+    When a user posts a link containing the old domain, the bot will automatically fix it to use the new domain.
+    Provide no second domain to disable link fixing.
+  ex:
+    - 'twitter.com vxtwitter.com'
+    - 'x.com'
+  params:
+    - oldDomain:
+        desc: "The domain to be replaced."
+      newDomain:
+        desc: "The domain to replace with."
+linkfixlist:
+  desc: |-
+    Lists all configured link fixes for the server.
+  ex:
+    - ''
+  params:
+    - { }
\ No newline at end of file
diff --git a/src/EllieBot/strings/responses/responses.en-US.json b/src/EllieBot/strings/responses/responses.en-US.json
index 6ad7a04..8f9b283 100644
--- a/src/EllieBot/strings/responses/responses.en-US.json
+++ b/src/EllieBot/strings/responses/responses.en-US.json
@@ -1230,5 +1230,13 @@
   "livechannel_list_empty": "No live channels configured for this server.",
   "livechannel_please_wait": "Please allow up to 10 minutes for the changes to take effect",
   "template": "Template",
-  "preview": "Preview"
+  "preview": "Preview",
+  "linkfix_invalid_domains": "Both old and new domains must be valid.",
+  "linkfix_invalid_domain": "The domain must be valid.",
+  "linkfix_added": "Links from {0} will now be fixed to {1}.",
+  "linkfix_already_exists": "A link fix for {0} already exists.",
+  "linkfix_list_none": "No link fixes have been configured for this server.",
+  "linkfix_list_title": "Link Fixes",
+  "linkfix_removed": "Link fix for {0} has been removed.",
+  "linkfix_not_found": "No link fix found for {0}."
 }
\ No newline at end of file