├── .gitattributes ├── .gitignore ├── LICENSE ├── LQ1Bot.sln ├── LQ1Bot ├── CreeperDetector.cs ├── Interface │ ├── IFriendMessage.cs │ ├── IGroupMessage.cs │ └── ITempMessage.cs ├── LQ1Bot.cs ├── LQ1Bot.csproj ├── LQ1BotConfig.cs ├── Meme │ ├── MemeBase.cs │ └── MemeManager.cs ├── OsuAPI.cs ├── PluginBase.cs ├── PluginController.cs ├── Plugins │ ├── Alarm.cs │ ├── AutoTranslate.cs │ ├── CatPic.cs │ ├── CreeperDetect.cs │ ├── DDTool.cs │ ├── DebugTool.cs │ ├── DestinyQuery.cs │ ├── Dice.cs │ ├── ExceptionGenerator.cs │ ├── FunctionSwitch.cs │ ├── Hitokoto.cs │ ├── HomoCalc.cs │ ├── KusaRecorder.cs │ ├── LiveNotify.cs │ ├── LivePrompt.cs │ ├── Meme.cs │ ├── MsgInform.cs │ ├── Mute.cs │ ├── OsuQuery.cs │ ├── PermissionMgr.cs │ ├── Picker.cs │ ├── RndPwdGen.cs │ ├── SwitchControl.cs │ ├── Translater.cs │ ├── Weather.cs │ └── WhatIsThis.cs ├── Program.cs └── Utils.cs └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb 341 | 342 | # Light_Quanta[1]; Bot Secret 343 | [Ss]ecret/ -------------------------------------------------------------------------------- /LQ1Bot.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30406.217 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LQ1Bot", "LQ1Bot\LQ1Bot.csproj", "{9C50AC2E-2375-4CB8-A6D9-03C24EC561EA}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {9C50AC2E-2375-4CB8-A6D9-03C24EC561EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {9C50AC2E-2375-4CB8-A6D9-03C24EC561EA}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {9C50AC2E-2375-4CB8-A6D9-03C24EC561EA}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {9C50AC2E-2375-4CB8-A6D9-03C24EC561EA}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {06447542-FB2B-4AA2-8AA3-E94D98D67A7F} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /LQ1Bot/CreeperDetector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Web; 8 | using TinyPinyin; 9 | 10 | namespace LQ1Bot { 11 | 12 | internal static class CreeperDetector { 13 | #region 终极爬行者检测模块 14 | 15 | public static bool IsCreeper(string msg) { 16 | msg = CharReplace(msg); 17 | msg += Reverse(msg); 18 | if (Regex.IsMatch(msg, @"^.*([机木]{1,}.{0,6}器{1,}.{0,6}人{1,}.{0,300}爬)|(爬{1,}.{0,300}[机木]{1,}.{0,6}器{1,}.{0,6}人).*$") || 19 | Regex.IsMatch(msg, @"^.*(b{1,}[^\w]{0,10}o{1,}[^\w]{0,10}t{1,}.{0,50}爬)|(爬{1,}.{0,50}b{1,}[^\w]{0,10}o{1,}[^\w]{0,10}t).*$")) { 20 | Console.ForegroundColor = ConsoleColor.Yellow; 21 | Console.WriteLine(msg); 22 | Console.ResetColor(); 23 | return true; 24 | } else { 25 | return false; 26 | } 27 | } 28 | 29 | private static string CharReplace(string s) { 30 | s = s.Trim(); 31 | #region base64解码 32 | foreach (Match match in Regex.Matches(s, @"((([a-zA-Z0-9\\\+]{4})*([a-zA-Z0-9\\\+]{3})=)|(([a-zA-Z0-9\\\+]{4})*([a-zA-Z0-9\\\+]{2})==)|[a-zA-Z0-9\\\+]{4})+")) { 33 | try { 34 | s += Encoding.UTF8.GetString(Convert.FromBase64String(match.Value)); 35 | } catch (Exception) { } 36 | } 37 | #endregion 38 | #region 熊曰解密 39 | foreach (Match match in Regex.Matches(s, @"熊曰:[\u4e00-\u9fa5]+")) { 40 | string result = ""; 41 | HttpWebRequest req = (HttpWebRequest) WebRequest.Create(@"http://hi.pcmoe.net/bear.php"); 42 | req.Timeout = 1000; 43 | req.Headers.Add("X-Token", "D398E4D76D4E"); 44 | req.Headers.Add("X-Requested-With", "XMLHttpRequest"); 45 | req.ContentType = "application/x-www-form-urlencoded"; 46 | req.Referer = "http://hi.pcmoe.net/index.html"; 47 | req.Method = "POST"; 48 | byte[] bs = Encoding.UTF8.GetBytes("mode=Bear&code=Decode&txt=" + HttpUtility.UrlEncode(match.Value)); 49 | req.ContentLength = bs.Length; 50 | Stream reqStream = req.GetRequestStream(); 51 | reqStream.Write(bs, 0, bs.Length); 52 | reqStream.Close(); 53 | try { 54 | HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); 55 | Stream stream = resp.GetResponseStream(); 56 | using (StreamReader reader = new StreamReader(stream)) { 57 | result = reader.ReadToEnd(); 58 | } 59 | stream.Close(); 60 | } catch (Exception) { } 61 | s += result; 62 | } 63 | #endregion 64 | #region 佛曰解密 65 | foreach (Match match in Regex.Matches(s, @"新佛曰:[\u4e00-\u9fa5]+")) { 66 | string result = ""; 67 | HttpWebRequest req = (HttpWebRequest) WebRequest.Create(@"http://hi.pcmoe.net/bear.php"); 68 | req.Timeout = 1000; 69 | req.Headers.Add("X-Token", "D398E4D76D4E"); 70 | req.Headers.Add("X-Requested-With", "XMLHttpRequest"); 71 | req.ContentType = "application/x-www-form-urlencoded"; 72 | req.Referer = "http://hi.pcmoe.net/index.html"; 73 | req.Method = "POST"; 74 | byte[] bs = Encoding.UTF8.GetBytes("mode=Buddha&code=Decode&txt=" + HttpUtility.UrlEncode(match.Value)); 75 | req.ContentLength = bs.Length; 76 | Stream reqStream = req.GetRequestStream(); 77 | reqStream.Write(bs, 0, bs.Length); 78 | reqStream.Close(); 79 | try { 80 | HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); 81 | Stream stream = resp.GetResponseStream(); 82 | using (StreamReader reader = new StreamReader(stream)) { 83 | result = reader.ReadToEnd(); 84 | } 85 | stream.Close(); 86 | } catch (Exception) { } 87 | s += result; 88 | } 89 | #endregion 90 | #region 摩斯电码解码 91 | s = s.Replace("----.", "9") 92 | .Replace("---..", "8") 93 | .Replace("--...", "7") 94 | .Replace("-....", "6") 95 | .Replace(".....", "5") 96 | .Replace("....-", "4") 97 | .Replace("...--", "3") 98 | .Replace("..---", "2") 99 | .Replace(".----", "1") 100 | .Replace("-----", "0") 101 | .Replace("..-..", "E") 102 | .Replace("--..", "Z") 103 | .Replace("-.--", "Y") 104 | .Replace("-..-", "X") 105 | .Replace("...-", "V") 106 | .Replace("--.-", "Q") 107 | .Replace(".--.", "P") 108 | .Replace(".-..", "L") 109 | .Replace(".---", "J") 110 | .Replace("....", "H") 111 | .Replace("..-..", "F") 112 | .Replace("-.-.", "C") 113 | .Replace("-...", "B") 114 | .Replace(".--", "W") 115 | .Replace("..-", "U") 116 | .Replace("...", "S") 117 | .Replace(".-.", "R") 118 | .Replace("---", "O") 119 | .Replace("-.-", "K") 120 | .Replace("--.", "G") 121 | .Replace("-..", "D") 122 | .Replace("-.", "N") 123 | .Replace("--", "M") 124 | .Replace("..", "I") 125 | .Replace(".-", "A") 126 | .Replace("-", "T") 127 | .Replace(".", "E"); 128 | #endregion 129 | #region UNICODE 130 | foreach (Match match in Regex.Matches(s, @"\\u[0-9a-f]{4}")) { 131 | int code = Convert.ToInt32(match.Value[2..], 16); 132 | s += (char) code; 133 | } 134 | #endregion 135 | s = s.ToLower(); 136 | s = s.Replace(" ", ""); 137 | s = s.Replace("[1]", ""); 138 | s = s.Replace("Π", "机"); 139 | s = Regex.Replace(s, @"[ΩㄇΠ♬]", "机"); 140 | s = s.Replace("_(•̀ω•́」∠)_", "爬"); 141 | s = s.Replace("表情117", "爬"); 142 | s = s.Replace("表情208", "爬"); 143 | s = s.Replace("Õ", "o"); 144 | s = Regex.Replace(s, @"[\n ,.?!。,?!_-]", ""); 145 | s = s.Replace("machine", "机器"); 146 | s = s.Replace("chicken", "机"); 147 | s = s.Replace("jqrp", "机器人爬"); 148 | s = s.Replace("gas", "器"); 149 | s = s.Replace("man", "人"); 150 | s = s.Replace("亻", "人"); 151 | s = s.Replace("ㄐㄧ", "机"); 152 | s = s.Replace("ㄑㄧˋ", "器"); 153 | s = s.Replace("ㄖㄣˊ", "人"); 154 | s = s.Replace("ㄆㄚˊ", "爬"); 155 | s = s.Replace("ㄅㄚ", "爬"); 156 | s = s.Replace("怕", ""); 157 | s = Regex.Replace(s, "zhua.{0,2}ba", "爬"); 158 | s = Regex.Replace(s, @"[口ロ]+.?[ボ木术]+.?ッ+.?[ト卜ド]|🤖|篮.?球|🏀|lq|basketball|lq|lightquanta", "机器人"); 159 | s = Regex.Replace(s, @"[啪钯杷耙琶葩趴扒耙鈀🧗啪🚼🦂巴巳パぱ⑧筢䯲掱苩]|c.*r.*a.*w.*l|c.*r.*e.*p|c.*l.*i.*m.*b|pa|滚|匍.*匐|g.*u.*n|pa", "爬"); 160 | s = Regex.Replace(s, @"[g機幾几🐓萝罗螺j🐔稽𓄿🐣🐤🐥じⓙ羁激]|j[i1]", "机"); 161 | s = Regex.Replace(s, @"[🏇噐博卜伯q械戒⑦7七柒犬💭🚴🚵☁气氣💨哭Ⓠ屑ち球求♟️]|大[·`‘’']|q[i1]", "器"); 162 | s = Regex.Replace(s, @"[👨人亼特口rɹ仌秂亽仁👤👦👨👥👴银淫亻慢曼漫🧍Ⓡ入恁]|れん|[rl][eᴱ3][и∩n]", "人"); 163 | string temp = ""; 164 | var c = new List(s.ToCharArray()); 165 | c.ForEach(x => { 166 | if (PinyinHelper.IsChinese(x)) { 167 | string rep = PinyinHelper.GetPinyin(x).ToLower(); 168 | temp += rep switch 169 | { 170 | "ji" => "机", 171 | "qi" => "器", 172 | "ren" => "人", 173 | "pa" => "爬", 174 | "bo" => "bo", 175 | "te" => "te", 176 | _ => x, 177 | }; 178 | } else { 179 | temp += x; 180 | } 181 | }); 182 | s += temp; 183 | s = s.Replace("ᗷ", "b"); 184 | s = Regex.Replace(s, @"13|[βⒷ6Ь♭вΒ🅱𝒃𝕓𝓫𝔟𝐛𝗯𝘣𝙗𝚋𝖇🄱🅑ⓑᵇb🇧​𝒷ꃳꋰ฿ᵇც]", "b"); 185 | s = Regex.Replace(s, @"[口0oοоОΟ🅾〇⚪⭕〇⚫Ⓞ𝒐𝕠𝓸𝔬𝐨𝗼𝘰𝙤𝚘𝖔🄾🅞ⓞᵒo𝚘𝑜ꄲŐθꂦ⊙•́⚽Ø🏀ÕᵒõΟơ]", "o"); 186 | s = Regex.Replace(s, @"[Ⓣᵀт丅𝒕𝕥𝓽𝐭𝔱𝘁𝘵𝙩𝚝𝖙🆃🅃🅣ⓣᵗt𝚝𝓉꓄Ťꋖ☂ɬ₮┬ᵗΤΓτť]", "t"); 187 | s = Regex.Replace(s, @"[Ⓟ𝒑𝓹𝔭𝕡𝐩𝗽𝘱𝙥𝚙𝖕🅿🄿🅟ⓟᵖp𝚙𝓅ᴘρþ]", "p"); 188 | s = Regex.Replace(s, @"[α𝒂𝕒𝓪𝔞𝐚𝗮𝘢𝙖𝚊𝖆🅰🄰🅐ⓐᵃa𝚊𝒶ⒶᴀΛáã𠆢Â]", "a"); 189 | s = Regex.Replace(s, @"p.{0,5}a", "爬"); 190 | if (Regex.IsMatch(s, @"^机器人.{0,10}p$")) 191 | return "机器人爬"; 192 | return s; 193 | } 194 | 195 | #endregion 196 | 197 | public static string Reverse(string ReverseString) { 198 | String output = string.Empty; 199 | for (int i = ReverseString.Length; i > 0; i--) { 200 | output += ReverseString.Substring(i - 1, 1); 201 | } 202 | return output; 203 | } 204 | } 205 | } -------------------------------------------------------------------------------- /LQ1Bot/Interface/IFriendMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using Mirai.Net.Data.Messages.Receivers; 6 | 7 | namespace LQ1Bot.Interface { 8 | interface IFriendMessage { 9 | Task FriendMessage(FriendMessageReceiver e); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LQ1Bot/Interface/IGroupMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using Mirai.Net.Data.Messages.Receivers; 6 | 7 | namespace LQ1Bot.Interface { 8 | interface IGroupMessage { 9 | Task GroupMessage(GroupMessageReceiver e); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LQ1Bot/Interface/ITempMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using Mirai.Net.Data.Messages.Receivers; 6 | 7 | namespace LQ1Bot.Interface { 8 | interface ITempMessage { 9 | Task TempMessage(TempMessageReceiver e); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LQ1Bot/LQ1Bot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reactive.Linq; 3 | using System.Threading.Tasks; 4 | using LQ1Bot.Interface; 5 | using Mirai.Net.Data.Events.Concretes.Request; 6 | using Mirai.Net.Data.Messages.Receivers; 7 | using Mirai.Net.Sessions; 8 | using Mirai.Net.Sessions.Http.Managers; 9 | 10 | namespace LQ1Bot { 11 | 12 | partial class LQ1Bot { 13 | private static LQ1BotConfig Secret; 14 | 15 | //public async Task Disconnected(MiraiHttpSession session, IDisconnectedEventArgs e) { 16 | // MiraiHttpSessionOptions options = new MiraiHttpSessionOptions(Secret.MiraiIp, Secret.MiraiPort, Secret.MiraiSecret); 17 | // while (true) { 18 | // try { 19 | // await session.ConnectAsync(options, Secret.QQ); // 连到成功为止, QQ号自填, 你也可以另行处理重连的 behaviour 20 | // return true; 21 | // } catch (Exception) { 22 | // await Task.Delay(1000); 23 | // } 24 | // } 25 | //} 26 | 27 | //public async Task NewFriendApply(MiraiHttpSession session, INewFriendApplyEventArgs e) { 28 | // await session.HandleNewFriendApplyAsync(e, FriendApplyAction.Allow, "感谢加好友哼哼啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊"); 29 | // return false; 30 | //} 31 | 32 | public LQ1Bot(LQ1BotConfig config, MiraiBot bot) { 33 | Secret = config; 34 | OsuAPI.OsuApiId = config.OsuApiId; 35 | OsuAPI.OsuApiSecret = config.OsuApiSecret; 36 | 37 | bot.EventReceived 38 | .OfType() 39 | .Subscribe(receiver => { 40 | RequestManager.HandleNewFriendRequestedAsync(receiver, Mirai.Net.Data.Shared.NewFriendRequestHandlers.Approve); 41 | } 42 | ); 43 | bot.MessageReceived 44 | .OfType() 45 | .Subscribe(receiver => { 46 | MessageManager.SendTempMessageAsync(receiver.GroupId, receiver.Sender.Id, "请先添加好友"); 47 | }); 48 | bot.EventReceived 49 | .OfType() 50 | .Subscribe(receiver => { 51 | RequestManager.HandleNewInvitationRequestedAsync(receiver, Mirai.Net.Data.Shared.NewInvitationRequestHandlers.Approve, ""); 52 | }); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /LQ1Bot/LQ1Bot.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | 973fc775-2cd3-42b4-b3f7-457b6ae30935 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /LQ1Bot/LQ1BotConfig.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Text.Encodings.Web; 3 | using System.Text.Json; 4 | using System.Text.Unicode; 5 | 6 | namespace LQ1Bot { 7 | 8 | internal class LQ1BotConfig { 9 | public string BaiduTranslateAppId { get; set; } 10 | public string BaiduTranslateSecret { get; set; } 11 | 12 | public string OsuApiSecret { get; set; } 13 | public string OsuApiId { get; set; } 14 | 15 | public string AliyunClientId { get; set; } 16 | public string AliyunClientSecret { get; set; } 17 | 18 | public string MiraiIp { get; set; } 19 | public string MiraiSecret { get; set; } 20 | public int MiraiPort { get; set; } 21 | public long QQ { get; set; } 22 | public string ApexSecret { get; set; } 23 | 24 | public string MemeBackupDirectory { get; set; } 25 | 26 | public void Init() { 27 | if (File.Exists("lq1bot.config")) { 28 | var v = JsonSerializer.Deserialize(File.ReadAllText("lq1bot.config")); 29 | //我也不知道该怎么读取比较好了 30 | //你们有没有什么比较好的读取方式 31 | MemeBackupDirectory = v.MemeBackupDirectory; 32 | QQ = v.QQ; 33 | MiraiIp = v.MiraiIp; 34 | MiraiPort = v.MiraiPort; 35 | MiraiSecret = v.MiraiSecret; 36 | AliyunClientId = v.AliyunClientId; 37 | AliyunClientSecret = v.AliyunClientSecret; 38 | OsuApiId = v.OsuApiId; 39 | OsuApiSecret = v.OsuApiSecret; 40 | BaiduTranslateAppId = v.BaiduTranslateAppId; 41 | BaiduTranslateSecret = v.BaiduTranslateSecret; 42 | ApexSecret = v.ApexSecret; 43 | } else { 44 | File.Create("lq1bot.config"); 45 | //格式化保存json,方便阅读 46 | var o = new JsonSerializerOptions() { 47 | Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), 48 | WriteIndented = true 49 | }; 50 | File.WriteAllText("lq1bot.config", JsonSerializer.Serialize(this, o)); 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /LQ1Bot/Meme/MemeBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace LQ1Bot.Meme { 4 | 5 | internal class MemeBase { 6 | 7 | /// 8 | /// 发言检测类型(普通检测,正则表达式匹配,正则表达式替换,指定内容开头检测) 9 | /// 10 | public enum MatchType { 11 | Equal, RegexMatch, RegexReplace, StartsWith 12 | } 13 | 14 | /// 15 | /// 定义文本检测的类型 16 | /// 17 | public MatchType DetectType { get; set; } 18 | 19 | /// 20 | /// meme的名称(也是要检测的文本) 21 | /// 22 | public string Name { get; set; } 23 | 24 | /// 25 | /// meme的别名 26 | /// 27 | public HashSet Alias { get; set; } 28 | 29 | /// 30 | /// 要回复的内容 31 | /// 32 | public HashSet ReplyContent { get; set; } 33 | 34 | /// 35 | /// 对于此meme的群白名单 36 | /// 37 | public HashSet WhitelistGroups { get; set; } 38 | 39 | /// 40 | /// 对于此meme的群黑名单 41 | /// 42 | public HashSet BlacklistGroups { get; set; } 43 | } 44 | } -------------------------------------------------------------------------------- /LQ1Bot/Meme/MemeManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text.Encodings.Web; 6 | using System.Text.Json; 7 | using System.Text.Json.Serialization; 8 | using System.Text.RegularExpressions; 9 | using System.Text.Unicode; 10 | 11 | namespace LQ1Bot.Meme { 12 | 13 | internal class MemeManager { 14 | private HashSet memes = new HashSet(); 15 | 16 | [JsonIgnore] 17 | public int MemeCount { get; } 18 | 19 | [JsonIgnore] 20 | public string SavePath { get; set; } 21 | 22 | public long LastUpdateTime { get; set; } 23 | //public List Admin { get; set; } 24 | 25 | public HashSet Memes { 26 | get => memes; 27 | set { 28 | LastUpdateTime = DateTimeOffset.Now.ToUnixTimeSeconds(); 29 | memes = value; 30 | } 31 | } 32 | 33 | //public bool IsAdmin(long qq) => Admin?.Contains(qq) ?? false; 34 | 35 | public string GetMeme(string MemeName) { 36 | foreach (var m in memes) { 37 | if (m.Name == MemeName.ToLower() || (m.Alias?.Contains(MemeName.ToLower()) ?? false)) { 38 | return string.Join("|", m.ReplyContent); 39 | } 40 | } 41 | return null; 42 | } 43 | 44 | public bool SetMeme(string MemeName, HashSet Content, MemeBase.MatchType Type = MemeBase.MatchType.Equal) { 45 | RemoveMeme(MemeName); 46 | return AddNewMeme(MemeName, Content.ToHashSet(), Type); 47 | } 48 | 49 | public bool SetMeme(string MemeName, params string[] Content) { 50 | return SetMeme(MemeName, Content.ToHashSet()); 51 | } 52 | 53 | public bool AddMemeReply(string MemeName, params string[] Content) { 54 | return AddMemeReply(MemeName, Content.ToHashSet()); 55 | } 56 | 57 | public bool AddMemeReply(string MemeName, HashSet Content) { 58 | bool modified = false; 59 | bool hasMeme = false; 60 | foreach (var m in Memes) { 61 | if (m.Name == MemeName.ToLower() || (m.Alias?.Contains(MemeName.ToLower()) ?? false)) { 62 | hasMeme = true; 63 | foreach (var v in Content) { 64 | if (m.ReplyContent.Add(v)) { 65 | modified = true; 66 | LastUpdateTime = DateTimeOffset.Now.ToUnixTimeSeconds(); 67 | } 68 | } 69 | } 70 | } 71 | if (!hasMeme) { 72 | Memes.Add(new MemeBase() { Name = MemeName, ReplyContent = Content }); 73 | modified = true; 74 | LastUpdateTime = DateTimeOffset.Now.ToUnixTimeSeconds(); 75 | } 76 | return modified; 77 | } 78 | 79 | public bool AddNewMeme(string MemeName, params string[] Content) { 80 | return AddNewMeme(MemeName, Content.ToHashSet()); 81 | } 82 | 83 | public bool AddNewMeme(string MemeName, string Content, MemeBase.MatchType Type = MemeBase.MatchType.Equal, HashSet MemeAlias = null, HashSet Whitelist = null, HashSet Blacklist = null) { 84 | return AddNewMeme(MemeName, new HashSet() { Content }, Type, MemeAlias, Whitelist, Blacklist); 85 | } 86 | 87 | public bool AddNewMeme(string MemeName, HashSet Content, MemeBase.MatchType Type = MemeBase.MatchType.Equal, HashSet MemeAlias = null, HashSet Whitelist = null, HashSet Blacklist = null) { 88 | foreach (var m in Memes) { 89 | if (m.Name == MemeName.ToLower() || (m.Alias?.Contains(MemeName.ToLower()) ?? false)) { 90 | return false; 91 | } 92 | } 93 | LastUpdateTime = DateTimeOffset.Now.ToUnixTimeSeconds(); 94 | return Memes.Add(new MemeBase() { 95 | Name = MemeName.ToLower(), 96 | DetectType = Type, 97 | ReplyContent = Content, 98 | Alias = MemeAlias, 99 | BlacklistGroups = Blacklist, 100 | WhitelistGroups = Whitelist, 101 | }); 102 | } 103 | 104 | public bool RemoveMeme(string MemeName) { 105 | foreach (var m in Memes) { 106 | if (m.Name == MemeName.ToLower() || (m.Alias?.Contains(MemeName.ToLower()) ?? false)) { 107 | LastUpdateTime = DateTimeOffset.Now.ToUnixTimeSeconds(); 108 | return Memes.Remove(m); 109 | } 110 | } 111 | return false; 112 | } 113 | 114 | public bool AddMemeAlias(string MemeName, params string[] Alias) { 115 | return AddMemeAlias(MemeName, Alias.ToHashSet()); 116 | } 117 | 118 | public bool AddMemeAlias(string MemeName, HashSet Alias) { 119 | foreach (var m in memes) { 120 | if (m.Name == MemeName.ToLower() || (m.Alias?.Contains(MemeName.ToLower()) ?? false)) { 121 | foreach (var v in Alias) { 122 | if (m.Alias == null) { 123 | m.Alias = new HashSet(); 124 | } 125 | if (m.Name != v.ToLower()) { 126 | m.Alias.Add(v.ToLower()); 127 | } 128 | } 129 | return true; 130 | } 131 | } 132 | return false; 133 | } 134 | 135 | public bool HasReply(string msg) { 136 | foreach (var m in memes) { 137 | switch (m.DetectType) { 138 | case MemeBase.MatchType.RegexMatch: 139 | case MemeBase.MatchType.RegexReplace: 140 | if (Regex.IsMatch(msg.ToLower(), m.Name)) { 141 | return true; 142 | } else { 143 | if (m.Alias != null) { 144 | foreach (var a in m.Alias) { 145 | if (Regex.IsMatch(msg.ToLower(), a)) { 146 | return true; 147 | } 148 | } 149 | } 150 | } 151 | break; 152 | 153 | case MemeBase.MatchType.StartsWith: 154 | if (msg.ToLower().StartsWith(m.Name.ToLower())) { 155 | return true; 156 | } else { 157 | if (m.Alias != null) { 158 | foreach (var a in m.Alias) { 159 | if (msg.ToLower().StartsWith(a.ToLower())) { 160 | return true; 161 | } 162 | } 163 | } 164 | } 165 | break; 166 | 167 | default: 168 | if (m.Name == msg.ToLower() || (m.Alias?.Contains(msg.ToLower()) ?? false)) { 169 | return true; 170 | } 171 | break; 172 | } 173 | } 174 | return false; 175 | } 176 | 177 | public string GetReply(string msg, long group) { 178 | foreach (var m in memes) { 179 | if (m.WhitelistGroups != null) { 180 | if (!m.WhitelistGroups.Contains(group)) { 181 | continue; 182 | } 183 | } 184 | if (m.BlacklistGroups?.Contains(group) ?? false) { 185 | continue; 186 | } 187 | switch (m.DetectType) { 188 | case MemeBase.MatchType.RegexMatch: 189 | if (Regex.IsMatch(msg.ToLower(), m.Name)) { 190 | List rep = new List(); 191 | foreach (var v in m.ReplyContent) { 192 | rep.Add(v); 193 | } 194 | return rep[(new Random()).Next(rep.Count)]; 195 | } 196 | break; 197 | 198 | case MemeBase.MatchType.RegexReplace: 199 | if (Regex.IsMatch(msg.ToLower(), m.Name)) { 200 | List rep = new List(); 201 | foreach (var v in m.ReplyContent) { 202 | rep.Add(v); 203 | } 204 | var match = Regex.Match(msg.ToLower(), m.Name); 205 | string result = rep[(new Random()).Next(rep.Count)]; 206 | if (int.TryParse(match.Groups["id"].ToString(), out int id)) { 207 | if (id >= 1) { 208 | if (id > rep.Count) { 209 | id %= rep.Count; 210 | id++; 211 | } 212 | result = rep[id - 1]; 213 | } 214 | } 215 | return Regex.Replace(msg, m.Name, result); 216 | } 217 | break; 218 | 219 | case MemeBase.MatchType.StartsWith: 220 | if (msg.ToLower().StartsWith(m.Name.ToLower())) { 221 | List rep = new List(); 222 | foreach (var v in m.ReplyContent) { 223 | rep.Add(v); 224 | } 225 | return rep[(new Random()).Next(rep.Count)]; 226 | } else { 227 | if (m.Alias != null) { 228 | foreach (var a in m.Alias) { 229 | if (msg.ToLower().StartsWith(a.ToLower())) { 230 | List rep = new List(); 231 | foreach (var v in m.ReplyContent) { 232 | rep.Add(v); 233 | } 234 | return rep[(new Random()).Next(rep.Count)]; 235 | } 236 | } 237 | } 238 | } 239 | break; 240 | 241 | default: 242 | if (m.Name == msg.ToLower() || (m.Alias?.Contains(msg.ToLower()) ?? false)) { 243 | List rep = new List(); 244 | foreach (var v in m.ReplyContent) { 245 | rep.Add(v); 246 | } 247 | return rep[(new Random()).Next(rep.Count)]; 248 | } 249 | break; 250 | } 251 | } 252 | return null; 253 | } 254 | 255 | public string GetMemeJson(string MemeName) { 256 | foreach (var m in Memes) { 257 | if (m.Name == MemeName.ToLower() || (m.Alias?.Contains(MemeName.ToLower()) ?? false)) { 258 | var o = new JsonSerializerOptions() { 259 | Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), 260 | WriteIndented = true 261 | }; 262 | return JsonSerializer.Serialize(m, o); 263 | } 264 | } 265 | return null; 266 | } 267 | 268 | public override string ToString() { 269 | var o = new JsonSerializerOptions() { 270 | Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), 271 | }; 272 | return JsonSerializer.Serialize(this, o); 273 | } 274 | 275 | public string ToIndentedString() { 276 | var o = new JsonSerializerOptions() { 277 | Encoder = JavaScriptEncoder.Create(UnicodeRanges.All), 278 | WriteIndented = true 279 | }; 280 | return JsonSerializer.Serialize(this, o); 281 | } 282 | 283 | public static MemeManager Parse(string src) { 284 | return JsonSerializer.Deserialize(src); 285 | } 286 | 287 | public static MemeManager ReadFromFile(string Path) { 288 | return Parse(File.ReadAllText(Path)); 289 | } 290 | 291 | public void Save() { 292 | File.WriteAllText(SavePath, ToIndentedString()); 293 | } 294 | 295 | public void Save(string Path) { 296 | File.WriteAllText(Path, ToIndentedString()); 297 | } 298 | } 299 | } -------------------------------------------------------------------------------- /LQ1Bot/OsuAPI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Text; 6 | using Microsoft.Data.Sqlite; 7 | using Newtonsoft.Json; 8 | 9 | namespace LQ1Bot { 10 | 11 | public static class OsuAPI { 12 | public const string OSU = "osu"; 13 | public const string MANIA = "mania"; 14 | public const string CTB = "fruits"; 15 | public const string TAIKO = "taiko"; 16 | 17 | public static string mode = "osu"; 18 | 19 | #region POST GET模块 20 | 21 | /// 22 | /// 指定Post地址使用Get 方式获取全部字符串 23 | /// 24 | /// 请求后台地址 25 | /// 26 | public static string Post(string url, Dictionary dic) { 27 | string result = ""; 28 | HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url); 29 | req.Method = "POST"; 30 | req.ContentType = "application/x-www-form-urlencoded"; 31 | #region 添加Post 参数 32 | StringBuilder builder = new StringBuilder(); 33 | int i = 0; 34 | foreach (var item in dic) { 35 | if (i > 0) 36 | builder.Append("&"); 37 | builder.AppendFormat("{0}={1}", item.Key, item.Value); 38 | i++; 39 | } 40 | byte[] data = Encoding.UTF8.GetBytes(builder.ToString()); 41 | req.ContentLength = data.Length; 42 | using (Stream reqStream = req.GetRequestStream()) { 43 | reqStream.Write(data, 0, data.Length); 44 | reqStream.Close(); 45 | } 46 | #endregion 47 | HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); 48 | Stream stream = resp.GetResponseStream(); 49 | //获取响应内容 50 | using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { 51 | result = reader.ReadToEnd(); 52 | } 53 | return result; 54 | } 55 | 56 | #endregion 57 | 58 | public static string OsuApiId; 59 | public static string OsuApiSecret; 60 | 61 | public static string GetWithToken(string url, string token) { 62 | string result = ""; 63 | HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url); 64 | req.Headers.Set("Authorization", "Bearer " + token); 65 | req.AllowAutoRedirect = false; 66 | 67 | req.Method = "GET"; 68 | try { 69 | HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); 70 | Stream stream = resp.GetResponseStream(); 71 | //获取内容 72 | using (StreamReader reader = new StreamReader(stream, Encoding.UTF8)) { 73 | result = reader.ReadToEnd(); 74 | } 75 | return result; 76 | } catch (WebException e) { 77 | if (e.Response is HttpWebResponse response) { 78 | switch (response.StatusCode) { 79 | case HttpStatusCode.NotFound: 80 | return "404"; 81 | 82 | case HttpStatusCode.Redirect: 83 | return e.Response.Headers["Location"]; 84 | 85 | case HttpStatusCode.Unauthorized: 86 | return "auth"; 87 | } 88 | } else { 89 | return null; 90 | } 91 | return null; 92 | } 93 | } 94 | 95 | public static string GetOAuthToken(string OsuApiId, string OsuApiSecret) { 96 | Dictionary d = new Dictionary { 97 | { "client_id", OsuApiId }, 98 | { "client_secret", OsuApiSecret }, 99 | { "grant_type", "client_credentials" }, 100 | { "scope", "public" } 101 | }; 102 | string responce = Post(@"https://osu.ppy.sh/oauth/token", d); 103 | OAuthTokenResponce o = JsonConvert.DeserializeObject(responce); 104 | return o.access_token; 105 | } 106 | 107 | public static string GetUserInfo(string name, string token) { 108 | string rep = GetWithToken(@"https://osu.ppy.sh/api/v2/users/" + name + "/" + mode, token); 109 | if (rep != null) { 110 | return rep switch 111 | { 112 | "auth" => "auth", 113 | "404" => "404", 114 | _ => rep, 115 | }; 116 | } else { 117 | return null; 118 | } 119 | } 120 | 121 | public static PInfo Query(string name) { 122 | PInfo p; 123 | p.pp = 0; p.rank = 0; p.crank = 0; p.playcount = 0; 124 | try { 125 | SqliteConnection conn = new SqliteConnection("Data Source=osu.db"); 126 | conn.Open(); 127 | SqliteCommand cmd = new SqliteCommand("", conn) { 128 | CommandText = "select pp,rank,crank,playcount from " + OsuAPI.mode + " where name=@name;" 129 | }; 130 | 131 | cmd.Parameters.AddWithValue("@name", name); 132 | 133 | SqliteDataReader dr = cmd.ExecuteReader(); 134 | while (dr.Read()) { 135 | p.pp = Int32.Parse(dr[0].ToString()); 136 | p.rank = Int32.Parse(dr[1].ToString()); 137 | p.crank = Int32.Parse(dr[2].ToString()); 138 | p.playcount = Int32.Parse(dr[3].ToString()); 139 | } 140 | dr.Close(); 141 | 142 | /* 143 | cmd.CommandText = "select rank from " + OsuAPI.mode + " where name=@name;"; 144 | dr = cmd.ExecuteReader(); 145 | while (dr.Read()) { 146 | p.rank = Int32.Parse(dr[0].ToString()); 147 | } 148 | dr.Close(); 149 | 150 | cmd.CommandText = "select crank from " + OsuAPI.mode + " where name=@name;"; 151 | dr = cmd.ExecuteReader(); 152 | while (dr.Read()) { 153 | p.crank = Int32.Parse(dr[0].ToString()); 154 | } 155 | dr.Close(); 156 | 157 | cmd.CommandText = "select playcount from " + OsuAPI.mode + " where name=@name;"; 158 | dr = cmd.ExecuteReader(); 159 | while (dr.Read()) { 160 | p.playcount = Int32.Parse(dr[0].ToString()); 161 | } 162 | dr.Close(); 163 | */ 164 | conn.Close(); 165 | return p; 166 | } catch (Exception ex) { 167 | Console.WriteLine(ex.Message); 168 | return p; 169 | } 170 | } 171 | 172 | public static PInfo QueryInjectable(ref string name) { 173 | PInfo p; 174 | p.pp = 0; p.rank = 0; p.crank = 0; p.playcount = 0; 175 | SqliteConnection conn = new SqliteConnection("Data Source=osuInject.db"); 176 | conn.Open(); 177 | SqliteCommand cmd = new SqliteCommand("", conn); 178 | cmd.CommandText = "select pp,rank,crank,playcount,name from " + OsuAPI.mode + " where name=\'" + name + "\';"; 179 | SqliteDataReader dr = cmd.ExecuteReader(); 180 | while (dr.Read()) { 181 | p.pp = Int32.Parse(dr[0].ToString()); 182 | p.rank = Int32.Parse(dr[1].ToString()); 183 | p.crank = Int32.Parse(dr[2].ToString()); 184 | p.playcount = Int32.Parse(dr[3].ToString()); 185 | name = dr[4].ToString(); 186 | } 187 | dr.Close(); 188 | conn.Close(); 189 | return p; 190 | } 191 | 192 | public struct PInfo { 193 | public int pp; 194 | public int rank; 195 | public int crank; 196 | public int playcount; 197 | } 198 | 199 | public static void Update(string name, int pp, int rank, int crank, int playcount) { 200 | try { 201 | using SqliteConnection conn = new SqliteConnection("Data Source=osu.db"); 202 | conn.Open(); 203 | SqliteCommand cmd = new SqliteCommand("", conn) { 204 | CommandText = "select rank from " + OsuAPI.mode + " where name=@name;" 205 | }; 206 | cmd.Parameters.AddWithValue("@name", name); 207 | 208 | SqliteDataReader dr = cmd.ExecuteReader(); 209 | string s = "0"; 210 | while (dr.Read()) { 211 | s = dr[0].ToString(); 212 | } 213 | dr.Close(); 214 | 215 | if (s == "0") { 216 | cmd.CommandText = "insert into " + OsuAPI.mode + " values (@name," + pp + "," + rank + "," + crank + "," + playcount + ");"; 217 | cmd.ExecuteNonQuery(); 218 | } else { 219 | cmd.CommandText = "update " + OsuAPI.mode + " set pp=" + pp + " where name=@name;"; 220 | cmd.ExecuteNonQuery(); 221 | 222 | cmd.CommandText = "update " + OsuAPI.mode + " set rank=" + rank + " where name=@name;"; 223 | cmd.ExecuteNonQuery(); 224 | 225 | cmd.CommandText = "update " + OsuAPI.mode + " set crank=" + crank + " where name=@name;"; 226 | cmd.ExecuteNonQuery(); 227 | 228 | cmd.CommandText = "update " + OsuAPI.mode + " set playcount=" + playcount + " where name=@name;"; 229 | cmd.ExecuteNonQuery(); 230 | } 231 | } catch (Exception ex) { 232 | Console.WriteLine(ex.Message); 233 | } 234 | } 235 | 236 | public static string ReadToken() { 237 | string token = null; 238 | try { 239 | FileInfo fi = new FileInfo("osu.token"); 240 | Console.WriteLine(fi.LastWriteTime); 241 | if (DateTime.Compare(fi.LastWriteTime, fi.LastWriteTime.AddDays(1.0)) >= 0) { 242 | return UpdateToken(); 243 | } 244 | using StreamReader sr = new StreamReader("osu.token"); 245 | token = sr.ReadLine(); 246 | } catch (Exception) { 247 | return UpdateToken(); 248 | } 249 | return token; 250 | } 251 | 252 | public static string UpdateToken() { 253 | using (StreamWriter sw = new StreamWriter("osu.token")) { 254 | string token = OsuAPI.GetOAuthToken(OsuApiId, OsuApiSecret); 255 | sw.WriteLine(token); 256 | return token; 257 | } 258 | } 259 | } 260 | 261 | internal class OAuthTokenResponce { 262 | public string token_type { get; set; } 263 | public string expires_in { get; set; } 264 | public string access_token { get; set; } 265 | } 266 | } -------------------------------------------------------------------------------- /LQ1Bot/PluginBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace LQ1Bot.Plugins { 4 | 5 | internal abstract class PluginBase { 6 | public abstract int Priority { get; } 7 | 8 | public string ConfigPath { 9 | get { 10 | return Environment.CurrentDirectory + "/" + PluginName; 11 | } 12 | } 13 | 14 | public abstract string PluginName { get; } 15 | 16 | public abstract bool CanDisable { get; } 17 | } 18 | } -------------------------------------------------------------------------------- /LQ1Bot/PluginController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace LQ1Bot.Plugins { 6 | 7 | internal class PluginController { 8 | public static readonly List PluginInstance = new List(); 9 | 10 | public void LoadPlugins() { 11 | Console.ForegroundColor = ConsoleColor.Green; 12 | Console.WriteLine("已找到的插件"); 13 | var Type = Utils.GetSubClass(typeof(PluginBase)); 14 | foreach (var PluginType in Type.OrderBy(o => o.GetCustomAttributes(true))) { 15 | PluginBase Plugin = (PluginBase) Activator.CreateInstance(PluginType); 16 | PluginInstance.Add(Plugin); 17 | } 18 | foreach (var Plugin in PluginInstance.OrderByDescending(o => o.Priority)) { 19 | Console.WriteLine($"[{Plugin.Priority}]\t\t{Plugin.PluginName}"); 20 | } 21 | Console.ResetColor(); 22 | } 23 | 24 | public void ShowPlugins() { 25 | Console.ForegroundColor = ConsoleColor.Green; 26 | Console.WriteLine("所有已加载插件"); 27 | foreach (var Plugin in PluginInstance.OrderByDescending(o => o.Priority)) { 28 | Console.WriteLine($"[{Plugin.Priority}]\t{Plugin.PluginName}"); 29 | } 30 | Console.ResetColor(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/Alarm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Threading.Tasks; 8 | using System.Web; 9 | using LQ1Bot.Interface; 10 | using Mirai.Net.Data.Messages.Receivers; 11 | using Mirai.Net.Sessions.Http.Managers; 12 | using Newtonsoft.Json; 13 | using Newtonsoft.Json.Linq; 14 | 15 | namespace LQ1Bot.Plugins { 16 | 17 | internal class Alarm : PluginBase, IGroupMessage { 18 | public override int Priority => 9982; 19 | 20 | public override string PluginName => "Alarm"; 21 | 22 | public override bool CanDisable => true; 23 | 24 | 25 | public async Task GroupMessage(GroupMessageReceiver e) { 26 | string text = Utils.GetMessageText(e.MessageChain); 27 | string q = e.Sender.Group.Id; 28 | if ((text == "!delalarm") && PermissionMgr.IsGroupOrBotAdmin(e.Sender)) { 29 | if (AlarmExists(q)) { 30 | File.Delete($"alarmcfg/{q}.txt"); 31 | await MessageManager.SendGroupMessageAsync(q, "已移除所有警钟"); 32 | } else { 33 | await MessageManager.SendGroupMessageAsync(q, "本群还未添加警钟!"); 34 | } 35 | } 36 | if (text.StartsWith("!addalarm ") && PermissionMgr.IsGroupOrBotAdmin(e.Sender)) { 37 | string alarm = text[10..]; 38 | if (alarm.Length > 0 && alarm.Split("|").Length == 2) { 39 | string time = alarm.Split("|")[0]; 40 | string content = alarm.Split("|")[1]; 41 | Match m = Regex.Match(time, @"^(\d{1,4})-(\d{1,2})-(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$"); 42 | if (m.Success) { 43 | int year = int.Parse(m.Groups[1].Value); 44 | int month = int.Parse(m.Groups[2].Value); 45 | int date = int.Parse(m.Groups[3].Value); 46 | int hour = int.Parse(m.Groups[4].Value); 47 | int minute = int.Parse(m.Groups[5].Value); 48 | int second = int.Parse(m.Groups[6].Value); 49 | try { 50 | DateTime t = new(year, month, date, hour, minute, second); 51 | long tick = t.Ticks; 52 | List list = new(); 53 | if (AlarmExists(q)) { 54 | list.AddRange(GetAlarms(q)); 55 | } 56 | list.Add(tick + "|" + content); 57 | File.WriteAllText($"alarmcfg/{q}.txt", string.Join("\n", list)); 58 | await MessageManager.SendGroupMessageAsync(q, "成功添加警钟"); 59 | } catch (ArgumentOutOfRangeException) { 60 | await MessageManager.SendGroupMessageAsync(q, "时间输入错误!输入格式应为:\n年-月-日 时:分:秒|回复内容"); 61 | } 62 | } else { 63 | await MessageManager.SendGroupMessageAsync(q, "时间输入错误!输入格式应为:\n年-月-日 时:分:秒|回复内容"); 64 | } 65 | } else { 66 | await MessageManager.SendGroupMessageAsync(q, "警钟格式输入错误!输入格式应为:\n年-月-日 时:分:秒|回复内容"); 67 | } 68 | } 69 | 70 | if (text == "!getalarm") { 71 | if (AlarmExists(q)) { 72 | var alarms = GetAlarms(q); 73 | List msg = new(); 74 | 75 | foreach (var v in alarms) { 76 | string temp = v; 77 | string time = temp.Split("|")[0]; 78 | string content = temp.Split("|")[1]; 79 | var InitTime = new DateTime(long.Parse(time)); 80 | msg.Add($"{InitTime:yyyy-MM-dd HH:mm:ss}|{content}"); 81 | } 82 | await MessageManager.SendGroupMessageAsync(q, string.Join("\n", msg)); 83 | } else { 84 | await MessageManager.SendGroupMessageAsync(q, "本群还未添加警钟!"); 85 | } 86 | } 87 | 88 | if (text == "警钟" || text == "警钟长鸣" || text == "警钟敲烂") { 89 | if (AlarmExists(q)) { 90 | string temp = GetAlarms(q)[^1]; 91 | string time = temp.Split("|")[0]; 92 | string content = temp.Split("|")[1]; 93 | var InitTime = new DateTime(long.Parse(time)); 94 | var Now = DateTime.Now; 95 | var Diff = Now - InitTime; 96 | string DiffStr = $"{Diff.Days}天{Diff.Hours}小时{Diff.Minutes}分{Diff.Seconds}秒{Diff.Ticks % 10000000 / 10000}毫秒{Diff.Ticks % 10000 / 10}微秒{Diff.Ticks % 10}00纳秒"; 97 | await MessageManager.SendGroupMessageAsync(q, content.Replace("{time}", DiffStr)); 98 | } else { 99 | await MessageManager.SendGroupMessageAsync(q, "本群还没有警钟!"); 100 | } 101 | } 102 | var match = Regex.Match(text, @"^警钟(\d+)$"); 103 | if (match.Success) { 104 | if (AlarmExists(q)) { 105 | var alarms = GetAlarms(q); 106 | int id = int.Parse(match.Groups[1].Value); 107 | if (id >= 1 && id <= alarms.Length) { 108 | string temp = GetAlarms(q)[id - 1]; 109 | string time = temp.Split("|")[0]; 110 | string content = temp.Split("|")[1]; 111 | var InitTime = new DateTime(long.Parse(time)); 112 | var Now = DateTime.Now; 113 | var Diff = Now - InitTime; 114 | string DiffStr = $"{Diff.Days}天{Diff.Hours}小时{Diff.Minutes}分{Diff.Seconds}秒{Diff.Ticks % 10000000 / 10000}毫秒{Diff.Ticks % 10000 / 10}微秒{Diff.Ticks % 10}00纳秒"; 115 | await MessageManager.SendGroupMessageAsync(q, content.Replace("{time}", DiffStr)); 116 | } else { 117 | await MessageManager.SendGroupMessageAsync(q, "不存在该警钟!"); 118 | } 119 | } else { 120 | await MessageManager.SendGroupMessageAsync(q, "本群还没有警钟!"); 121 | } 122 | } 123 | 124 | if (text == "编钟") { 125 | if (AlarmExists(q)) { 126 | var alarms = GetAlarms(q); 127 | List msg = new(); 128 | 129 | foreach (var v in alarms) { 130 | string temp = v; 131 | string time = temp.Split("|")[0]; 132 | string content = temp.Split("|")[1]; 133 | var InitTime = new DateTime(long.Parse(time)); 134 | var Now = DateTime.Now; 135 | var Diff = Now - InitTime; 136 | string DiffStr = $"{Diff.Days}天{Diff.Hours}小时{Diff.Minutes}分{Diff.Seconds}秒{Diff.Ticks % 10000000 / 10000}毫秒{Diff.Ticks % 10000 / 10}微秒{Diff.Ticks % 10}00纳秒"; 137 | msg.Add(content.Replace("{time}", DiffStr)); 138 | } 139 | await MessageManager.SendGroupMessageAsync(q, string.Join("\n", msg)); 140 | } else { 141 | await MessageManager.SendGroupMessageAsync(q, "本群还没有警钟!"); 142 | } 143 | } 144 | return false; 145 | } 146 | 147 | private static string[] GetAlarms(string q) { 148 | return File.ReadAllLines($"alarmcfg/{q}.txt"); 149 | } 150 | private static bool AlarmExists(string q) { 151 | return File.Exists($"alarmcfg/{q}.txt"); 152 | } 153 | 154 | } 155 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/AutoTranslate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Security.Cryptography; 6 | using System.Text.RegularExpressions; 7 | using System.Threading.Tasks; 8 | using System.Web; 9 | using LQ1Bot.Interface; 10 | using Mirai.Net.Data.Messages.Receivers; 11 | using Mirai.Net.Sessions.Http.Managers; 12 | using Newtonsoft.Json.Linq; 13 | 14 | namespace LQ1Bot.Plugins { 15 | 16 | internal class AutoTranslate : PluginBase, IGroupMessage { 17 | public override int Priority => 9988; 18 | 19 | public override string PluginName => "AutoTranslate"; 20 | 21 | public override bool CanDisable => true; 22 | 23 | private readonly Dictionary AutoTranslateList = new Dictionary(); 24 | 25 | public AutoTranslate() { 26 | AutoTranslateList.Add("1057879872", "zh"); 27 | } 28 | 29 | public async Task GroupMessage(GroupMessageReceiver e) { 30 | string text = Utils.GetMessageText(e.MessageChain); 31 | #region 自动翻译 32 | if (Regex.IsMatch(text, @"^autotranslate \d+ \w+")) { 33 | if (long.TryParse(text.Split(' ')[1], out long target)) { 34 | string TargetLang = text.Split(' ')[2]; 35 | if (TargetLang == "reset") { 36 | AutoTranslateList.Remove(target.ToString()); 37 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id,$"已为QQ号{target}关闭自动翻译"); 38 | return true; 39 | } else { 40 | AutoTranslateList.Remove(target.ToString()); 41 | AutoTranslateList.Add(target.ToString(), text.Split(' ')[2]); 42 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, $"已为QQ号{target}开启自动翻译"); 43 | } 44 | } 45 | return true; 46 | } 47 | if (AutoTranslateList.ContainsKey(e.Sender.Id)) { 48 | string ToTranslate = text; 49 | string Lang = AutoTranslateList.GetValueOrDefault(e.Sender.Id); 50 | string AppId = Program.Secret.BaiduTranslateAppId; 51 | string salt = RandomNumberGenerator.GetInt32(1000000, 9999999).ToString(); 52 | Console.WriteLine(salt); 53 | string sign = Utils.GetMD5(AppId + ToTranslate + salt + Program.Secret.BaiduTranslateSecret); 54 | Console.WriteLine(sign); 55 | string url = @"http://" + @$"api.fanyi.baidu.com/api/trans/vip/translate?q={HttpUtility.UrlEncode(ToTranslate)}&from=auto&to={Lang}&appid={AppId}&salt={salt}&sign={sign}"; 56 | HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url); 57 | req.Timeout = 5000; 58 | string result = ""; 59 | try { 60 | HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); 61 | Stream stream = resp.GetResponseStream(); 62 | using (StreamReader reader = new StreamReader(stream)) { 63 | result = reader.ReadToEnd(); 64 | } 65 | stream.Close(); 66 | Console.WriteLine(result); 67 | JObject o = JObject.Parse(result); 68 | if (o["from"].ToString() != Lang) { 69 | string TranslationResult = o["trans_result"][0]["dst"].ToString(); 70 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id,$"【{TranslationResult}】"); 71 | } 72 | } catch (Exception) { } 73 | return false; 74 | } 75 | #endregion 76 | return false; 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/CatPic.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Flurl.Http; 4 | using LQ1Bot.Interface; 5 | using Mirai.Net.Data.Messages.Concretes; 6 | using Mirai.Net.Data.Messages.Receivers; 7 | using Mirai.Net.Sessions.Http.Managers; 8 | using Newtonsoft.Json.Linq; 9 | 10 | namespace LQ1Bot.Plugins { 11 | 12 | internal class CatPic : PluginBase, IGroupMessage, IFriendMessage { 13 | public override int Priority => 9983; 14 | 15 | public override string PluginName => "CatPic"; 16 | 17 | public override bool CanDisable => true; 18 | 19 | public async Task FriendMessage(FriendMessageReceiver e) { 20 | string text = Utils.GetMessageText(e.MessageChain); 21 | string q = e.Sender.Id; 22 | #region CatPic 23 | if (text == "来点猫猫" || text == "来点猫图") { 24 | try { 25 | string json = await "https://api.thecatapi.com/v1/images/search".GetStringAsync(); 26 | string id = JArray.Parse(json)[0]["url"].ToString(); 27 | ImageMessage image = new(); 28 | image.Url = id; 29 | await MessageManager.SendFriendMessageAsync(q, image); 30 | } catch (Exception ee) { 31 | Console.WriteLine(ee.Message); 32 | await MessageManager.SendFriendMessageAsync(q, "获取猫图出错"); 33 | } 34 | return true; 35 | } 36 | #endregion 37 | return false; 38 | } 39 | 40 | public async Task GroupMessage(GroupMessageReceiver e) { 41 | string text = Utils.GetMessageText(e.MessageChain); 42 | string q = e.Sender.Group.Id; 43 | #region CatPic 44 | if (text == "来点猫猫" || text == "来点猫图") { 45 | try { 46 | string json = await "https://api.thecatapi.com/v1/images/search".GetStringAsync(); 47 | string id = JArray.Parse(json)[0]["url"].ToString(); 48 | ImageMessage image = new(); 49 | image.Url = id; 50 | await MessageManager.SendGroupMessageAsync(q, image); 51 | } catch (Exception ee) { 52 | Console.WriteLine(ee.Message); 53 | await MessageManager.SendGroupMessageAsync(q, "获取猫图出错"); 54 | } 55 | return true; 56 | } 57 | #endregion 58 | return false; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/CreeperDetect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using LQ1Bot.Interface; 4 | using Microsoft.Data.Sqlite; 5 | using Mirai.Net.Data.Messages.Receivers; 6 | using Mirai.Net.Sessions.Http.Managers; 7 | 8 | namespace LQ1Bot.Plugins { 9 | 10 | internal class CreeperDetect : PluginBase, IGroupMessage, IFriendMessage, ITempMessage { 11 | public override int Priority => 10000; 12 | 13 | public override string PluginName => "CreeperDetector"; 14 | 15 | public override bool CanDisable => true; 16 | 17 | public async Task GroupMessage(GroupMessageReceiver e) { 18 | string text = Utils.GetMessageText(e.MessageChain); 19 | string q = e.Sender.Group.Id; 20 | if (e.Sender.Name.Length < 10 && CreeperDetector.IsCreeper(e.Sender.Name)) { 21 | try { 22 | await GroupManager.SetMemberInfoAsync(e.Sender.Id, q, "爬"); 23 | } catch (Exception eeeee) { 24 | Console.WriteLine(eeeee.Message); 25 | } 26 | } 27 | if (CreeperDetector.IsCreeper(text) && text.IndexOf("http://") == -1 && text.IndexOf("https://") == -1) { 28 | Console.ForegroundColor = ConsoleColor.DarkYellow; 29 | Console.WriteLine("已禁言用户"); 30 | Console.ResetColor(); 31 | await MessageManager.SendGroupMessageAsync(q, "就这?"); 32 | try { 33 | await GroupManager.MuteAsync(e.Sender.Id, q, TimeSpan.FromMinutes(5.0)); 34 | } catch (Exception) { } 35 | try { 36 | SqliteConnection conn = new SqliteConnection("Data Source=chat.db"); 37 | conn.Open(); 38 | SqliteCommand cmd = new SqliteCommand("", conn) { 39 | CommandText = $"insert into main values (strftime('%Y-%m-%d %H:%M:%f','now','localtime'),@nickname,{e.Sender.Id},{q},'creep')" 40 | }; 41 | cmd.Parameters.AddWithValue("@nickname", e.Sender.Name); 42 | 43 | SqliteDataReader dr = cmd.ExecuteReader(); 44 | dr.Close(); 45 | Console.ForegroundColor = ConsoleColor.DarkGreen; 46 | conn.Close(); 47 | 48 | Console.ResetColor(); 49 | } catch (Exception ee) { 50 | Console.ForegroundColor = ConsoleColor.Red; 51 | Console.WriteLine("写入数据库出现错误\n" + ee.Message); 52 | Console.ResetColor(); 53 | } 54 | return true; 55 | } 56 | return false; 57 | } 58 | 59 | public async Task FriendMessage(FriendMessageReceiver e) { 60 | if (CreeperDetector.IsCreeper(Utils.GetMessageText(e.MessageChain))) { 61 | await MessageManager.SendFriendMessageAsync(e.Sender.Id, "爬"); 62 | return true; 63 | } 64 | return false; 65 | } 66 | 67 | public async Task TempMessage(TempMessageReceiver e) { 68 | if (CreeperDetector.IsCreeper(Utils.GetMessageText(e.MessageChain))) { 69 | await MessageManager.SendTempMessageAsync(e.Sender.Id, e.Sender.Group.Id, "爬"); 70 | return true; 71 | } 72 | return false; 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/DDTool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text.Json; 5 | using System.Threading.Tasks; 6 | using Flurl.Http; 7 | using LQ1Bot.Interface; 8 | using Mirai.Net.Data.Messages.Concretes; 9 | using Mirai.Net.Data.Messages.Receivers; 10 | using Mirai.Net.Sessions.Http.Managers; 11 | using Mirai.Net.Utils.Scaffolds; 12 | using Newtonsoft.Json.Linq; 13 | 14 | namespace LQ1Bot.Plugins { 15 | 16 | internal class DDTool : PluginBase, IFriendMessage, IGroupMessage { 17 | public override int Priority => 9995; 18 | 19 | public override string PluginName => "DDTool"; 20 | 21 | public override bool CanDisable => true; 22 | 23 | private Dictionary Cooldown = new Dictionary(); 24 | private Dictionary Override = new Dictionary(); 25 | 26 | private string Api = "https://cfapi.vtbs.moe"; 27 | public DDTool() { 28 | try { 29 | Override = JsonSerializer.Deserialize>(File.ReadAllText("ddtoolcfg/config.json")); 30 | } catch (Exception ex) { 31 | Console.WriteLine(ex); 32 | if (File.Exists("ddtoolcfg/config.json")) { 33 | File.Move("ddtoolcfg/config.json", "ddtoolcfg/config.json.bak"); 34 | } 35 | File.WriteAllText("ddtoolcfg/config.json", JsonSerializer.Serialize(Override)); 36 | } 37 | } 38 | public async Task FriendMessage(FriendMessageReceiver e) { 39 | string text = Utils.GetMessageText(e.MessageChain).ToLower(); 40 | string q = e.Sender.Id; 41 | switch (text) { 42 | #region 今天看谁 43 | case "今天看谁": 44 | case "今天d谁": 45 | try { 46 | string res = await $"{Api}/v1/vtbs".GetStringAsync(); 47 | JArray Vtbs = JArray.Parse(res); 48 | 49 | int index = (new Random()).Next(Vtbs.Count); 50 | JObject RndVtbId = (JObject) Vtbs[index]; 51 | 52 | string userId = RndVtbId["mid"].ToString(); 53 | 54 | var RndVtb = JObject.Parse(await ($"{Api}/v1/detail/" + userId).GetStringAsync()); 55 | 56 | string userName = RndVtb["uname"].ToString(); 57 | string roomId = RndVtb["roomid"].ToString(); 58 | string faceUrl = RndVtb["face"].ToString() + "@150h"; 59 | string followers = RndVtb["follower"].ToString(); 60 | bool online = RndVtb["online"].ToObject(); 61 | string sign = RndVtb["sign"].ToString(); 62 | string title = RndVtb["title"].ToString(); 63 | if (online == false) { 64 | await MessageManager.SendFriendMessageAsync(q, new MessageChainBuilder() 65 | .ImageFromUrl(faceUrl) 66 | .Plain($@"名称:{userName} 67 | 签名:{sign} 68 | 粉丝数:{followers} 69 | 主页地址:https://space.bilibili.com/{userId} 70 | 直播间地址:https://live.bilibili.com/{roomId}").Build()); 71 | } else { 72 | await MessageManager.SendFriendMessageAsync(q, new MessageChainBuilder() 73 | .ImageFromUrl(faceUrl) 74 | .Plain($@"名称:{userName} 75 | 签名:{sign} 76 | 粉丝数:{followers} 77 | 主页地址:https://space.bilibili.com/{userId} 78 | 79 | 当前正在直播! 80 | 直播间标题:{title} 81 | 直播间地址:https://live.bilibili.com/{roomId}").Build()); 82 | } 83 | } catch (Exception ee) { 84 | Console.WriteLine(ee.Message); 85 | await MessageManager.SendFriendMessageAsync(q, "获取vtb信息出错"); 86 | } 87 | return true; 88 | #endregion 89 | #region 现在看谁 90 | case "现在看谁": 91 | case "现在d谁": 92 | try { 93 | string res = await $"{Api}/v1/living".GetStringAsync(); 94 | JArray Vtbs = JArray.Parse(res); 95 | 96 | int index = (new Random()).Next(Vtbs.Count); 97 | long RndVtbId = Vtbs[index].ToObject(); 98 | 99 | var RoomInfo = JObject.Parse(await ($"{Api}/v1/room/" + RndVtbId).GetStringAsync()); 100 | string uid = RoomInfo["uid"].ToString(); 101 | string popularity = RoomInfo["popularity"].ToString(); 102 | 103 | var RndVtb = JObject.Parse(await ($"{Api}/v1/detail/" + uid).GetStringAsync()); 104 | 105 | string userName = RndVtb["uname"].ToString(); 106 | string roomId = RndVtb["roomid"].ToString(); 107 | string faceUrl = RndVtb["face"].ToString() + "@150h"; 108 | string followers = RndVtb["follower"].ToString(); 109 | string online = RndVtb["online"].ToString(); 110 | string sign = RndVtb["sign"].ToString(); 111 | string title = RndVtb["title"].ToString(); 112 | 113 | await MessageManager.SendFriendMessageAsync(q, new MessageChainBuilder() 114 | .ImageFromUrl(faceUrl) 115 | .Plain($@"{title} 116 | https://live.bilibili.com/{roomId} 117 | 人气:{popularity} 118 | 119 | vtb信息 120 | 名称:{userName} 121 | 签名:{sign} 122 | 粉丝数:{followers} 123 | 主页地址:https://space.bilibili.com/{uid}").Build()); 124 | } catch (Exception ee) { 125 | Console.WriteLine(ee.Message); 126 | await MessageManager.SendFriendMessageAsync(q, "获取vtb信息出错"); 127 | } 128 | return true; 129 | #endregion 130 | default: 131 | return false; 132 | } 133 | } 134 | 135 | public async Task GroupMessage(GroupMessageReceiver e) { 136 | string text = Utils.GetMessageText(e.MessageChain).ToLower(); 137 | string q = e.Sender.Group.Id; 138 | switch (text) { 139 | #region 今天看谁 140 | case "今天看谁": 141 | case "今天d谁": 142 | if (Cooldown.ContainsKey(e.Sender.Id)) { 143 | DateTime d = Cooldown.GetValueOrDefault(e.Sender.Id); 144 | if ((DateTime.Now - d).TotalSeconds < 300) { 145 | return true; 146 | } 147 | } 148 | 149 | try { 150 | string userId; 151 | if (Override.TryGetValue(q, out string mid)) { 152 | userId = mid; 153 | var result = JObject.Parse(await ("http://api.bilibili.com/x/web-interface/card?mid=" + mid).GetStringAsync()); 154 | if (result["code"].ToString() == "0") { 155 | string name = result["data"]["card"]["name"].ToString(); 156 | string sign = result["data"]["card"]["sign"].ToString(); 157 | string followers = result["data"]["card"]["fans"].ToString(); 158 | 159 | await MessageManager.SendGroupMessageAsync(q, new MessageChainBuilder() 160 | .ImageFromUrl(result["data"]["card"]["face"].ToString() + "@150h") 161 | .Plain($@"名称:{name} 162 | 签名:{sign} 163 | 粉丝数:{followers} 164 | 主页地址:https://space.bilibili.com/{userId}").Build()); 165 | } else { 166 | await MessageManager.SendGroupMessageAsync(q, "获取vtb信息出错"); 167 | } 168 | } else { 169 | string res = await ($"{Api}/v1/vtbs").GetStringAsync(); 170 | JArray Vtbs = JArray.Parse(res); 171 | 172 | int index = (new Random()).Next(Vtbs.Count); 173 | JObject RndVtbId = (JObject) Vtbs[index]; 174 | userId = RndVtbId["mid"].ToString(); 175 | var RndVtb = JObject.Parse(await ($"{Api}/v1/detail/" + userId).GetStringAsync()); 176 | 177 | string userName = RndVtb["uname"].ToString(); 178 | string roomId = RndVtb["roomid"].ToString(); 179 | string faceUrl = RndVtb["face"].ToString() + "@150h"; 180 | string followers = RndVtb["follower"].ToString(); 181 | bool online = RndVtb["online"].ToObject(); 182 | string sign = RndVtb["sign"].ToString(); 183 | string title = RndVtb["title"].ToString(); 184 | string id = ""; 185 | 186 | if (online == false) { 187 | id = await MessageManager.SendGroupMessageAsync(q, new MessageChainBuilder() 188 | .ImageFromUrl(faceUrl) 189 | .Plain($@"名称:{userName} 190 | 签名:{sign} 191 | 粉丝数:{followers} 192 | 主页地址:https://space.bilibili.com/{userId} 193 | 直播间地址:https://live.bilibili.com/{roomId}").Build()); 194 | } else { 195 | id = await MessageManager.SendGroupMessageAsync(q, new MessageChainBuilder() 196 | .ImageFromUrl(faceUrl) 197 | .Plain($@"名称:{userName} 198 | 签名:{sign} 199 | 粉丝数:{followers} 200 | 主页地址:https://space.bilibili.com/{userId} 201 | 202 | 当前正在直播! 203 | 直播间标题:{title} 204 | 直播间地址:https://live.bilibili.com/{roomId}").Build()); 205 | } 206 | Cooldown.Remove(e.Sender.Id); 207 | Cooldown.Add(e.Sender.Id, DateTime.Now); 208 | } 209 | } catch (Exception ee) { 210 | Console.WriteLine(ee.Message); 211 | await MessageManager.SendGroupMessageAsync(q, "获取vtb信息出错"); 212 | } 213 | return true; 214 | #endregion 215 | #region 现在看谁 216 | case "现在看谁": 217 | case "现在d谁": 218 | if (Cooldown.ContainsKey(e.Sender.Id)) { 219 | DateTime d = Cooldown.GetValueOrDefault(e.Sender.Id); 220 | if ((DateTime.Now - d).TotalSeconds < 300) { 221 | return true; 222 | } 223 | } 224 | try { 225 | if (Override.TryGetValue(q, out string mid)) { 226 | var result = JObject.Parse(await ("http://api.bilibili.com/x/web-interface/card?mid=" + mid).GetStringAsync()); 227 | if (result["code"].ToString() == "0") { 228 | string name = result["data"]["card"]["name"].ToString(); 229 | string sign = result["data"]["card"]["sign"].ToString(); 230 | string followers = result["data"]["card"]["fans"].ToString(); 231 | 232 | await MessageManager.SendGroupMessageAsync(q, new MessageChainBuilder() 233 | .ImageFromUrl(result["data"]["card"]["face"].ToString() + "@150h") 234 | .Plain($@"名称:{name} 235 | 签名:{sign} 236 | 粉丝数:{followers} 237 | 主页地址:https://space.bilibili.com/{mid}").Build()); 238 | } else { 239 | await MessageManager.SendGroupMessageAsync(q, "获取vtb信息出错"); 240 | } 241 | } else { 242 | string res = await ($"{Api}/v1/living").GetStringAsync(); 243 | JArray Vtbs = JArray.Parse(res); 244 | 245 | int index = (new Random()).Next(Vtbs.Count); 246 | string RndVtbId = Vtbs[index].ToObject(); 247 | 248 | var RoomInfo = JObject.Parse(await ($"{Api}/v1/room/" + RndVtbId).GetStringAsync()); 249 | string uid = RoomInfo["uid"].ToString(); 250 | string popularity = RoomInfo["popularity"].ToString(); 251 | 252 | var RndVtb = JObject.Parse(await ($"{Api}/v1/detail/" + uid).GetStringAsync()); 253 | 254 | string userName = RndVtb["uname"].ToString(); 255 | string roomId = RndVtb["roomid"].ToString(); 256 | string faceUrl = RndVtb["face"].ToString() + "@150h"; 257 | string followers = RndVtb["follower"].ToString(); 258 | string online = RndVtb["online"].ToString(); 259 | string sign = RndVtb["sign"].ToString(); 260 | string title = RndVtb["title"].ToString(); 261 | string id = await MessageManager.SendGroupMessageAsync(q, new MessageChainBuilder() 262 | .ImageFromUrl(faceUrl) 263 | .Plain($@"{title} 264 | https://live.bilibili.com/{roomId} 265 | 人气:{popularity} 266 | 267 | vtb信息 268 | 名称:{userName} 269 | 签名:{sign} 270 | 粉丝数:{followers} 271 | 主页地址:https://space.bilibili.com/{uid}").Build()); 272 | Cooldown.Remove(e.Sender.Id); 273 | Cooldown.Add(e.Sender.Id, DateTime.Now); 274 | } 275 | } catch (Exception ee) { 276 | Console.WriteLine(ee.Message); 277 | await MessageManager.SendGroupMessageAsync(q, "获取vtb信息出错"); 278 | } 279 | return true; 280 | #endregion 281 | default: 282 | if (text.StartsWith("!setddtool ") && PermissionMgr.IsGroupOrBotAdmin(e.Sender)) { 283 | string uid = text[11..]; 284 | if (long.TryParse(uid, out long target)) { 285 | if (Override.ContainsKey(q)) { 286 | Override.Remove(q); 287 | } 288 | Override.Add(q, target.ToString()); 289 | File.WriteAllText("ddtoolcfg/config.json", JsonSerializer.Serialize(Override)); 290 | await MessageManager.SendGroupMessageAsync(q, "已设置DDTool指定抽取用户uid:" + target); 291 | } 292 | } 293 | return false; 294 | } 295 | } 296 | } 297 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/DebugTool.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using LQ1Bot.Interface; 4 | using Mirai.Net.Data.Messages.Concretes; 5 | using Mirai.Net.Data.Messages.Receivers; 6 | using Mirai.Net.Sessions.Http.Managers; 7 | 8 | namespace LQ1Bot.Plugins { 9 | 10 | internal class DebugTool : PluginBase, IFriendMessage, IGroupMessage { 11 | public override int Priority => 2000; 12 | 13 | public override string PluginName => "DebugTool"; 14 | 15 | public override bool CanDisable => true; 16 | 17 | public async Task FriendMessage(FriendMessageReceiver e) { 18 | string text = Utils.GetMessageText(e.MessageChain).ToLower(); 19 | if (text == "picinfo") { 20 | List picresult = new List(); 21 | foreach (var msg in e.MessageChain) { 22 | if (msg is ImageMessage tempmsg) { 23 | picresult.Add(tempmsg.ImageId + " " + tempmsg.Url + "\n"); 24 | } 25 | } 26 | if (picresult.Count > 0) { 27 | await MessageManager.SendFriendMessageAsync(e.Sender.Id, string.Join("\n", picresult)); 28 | } 29 | return true; 30 | } 31 | return false; 32 | } 33 | 34 | public async Task GroupMessage(GroupMessageReceiver e) { 35 | string text = Utils.GetMessageText(e.MessageChain).ToLower(); 36 | if (text == "picinfo") { 37 | List picresult = new List(); 38 | foreach (var msg in e.MessageChain) { 39 | if (msg is ImageMessage tempmsg) { 40 | picresult.Add(tempmsg.ImageId + " " + tempmsg.Url + "\n"); 41 | } 42 | } 43 | if (picresult.Count > 0) { 44 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, string.Join("\n", picresult)); 45 | } 46 | return true; 47 | } 48 | return false; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/DestinyQuery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Text.RegularExpressions; 4 | using System.Threading.Tasks; 5 | using LQ1Bot.Interface; 6 | using Mirai.Net.Data.Messages.Concretes; 7 | using Mirai.Net.Data.Messages.Receivers; 8 | using Mirai.Net.Sessions.Http.Managers; 9 | using Newtonsoft.Json.Linq; 10 | 11 | namespace LQ1Bot.Plugins { 12 | 13 | internal class DestinyQuery : PluginBase, IGroupMessage, IFriendMessage { 14 | public override int Priority => 9984; 15 | 16 | public override string PluginName => "DestinyQuery"; 17 | 18 | public override bool CanDisable => true; 19 | 20 | public async Task FriendMessage(FriendMessageReceiver e) { 21 | string text = Utils.GetMessageText(e.MessageChain); 22 | string q = e.Sender.Id; 23 | if (text == "日报") { 24 | try { 25 | WebClient wc = new WebClient(); 26 | string res = wc.DownloadString("http://www.tianque.top/d2api/today/"); 27 | JObject o = JObject.Parse(res); 28 | ImageMessage image = new ImageMessage(); 29 | image.Url = o["img_url"].ToString(); 30 | await MessageManager.SendFriendMessageAsync(q, image); 31 | } catch (Exception) { 32 | await MessageManager.SendFriendMessageAsync(q, "获取日报出错"); 33 | } 34 | return true; 35 | } 36 | return false; 37 | } 38 | 39 | public async Task GroupMessage(GroupMessageReceiver e) { 40 | string text = Utils.GetMessageText(e.MessageChain); 41 | string q = e.Sender.Group.Id; 42 | if (text == "日报") { 43 | try { 44 | WebClient wc = new WebClient(); 45 | string res = wc.DownloadString("http://www.tianque.top/d2api/today/"); 46 | JObject o = JObject.Parse(res); 47 | ImageMessage image = new ImageMessage(); 48 | image.Url = o["img_url"].ToString(); 49 | await MessageManager.SendGroupMessageAsync(q, image); 50 | } catch (Exception) { 51 | await MessageManager.SendGroupMessageAsync(q, "获取日报出错"); 52 | } 53 | return true; 54 | } 55 | return false; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/Dice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using System.Threading.Tasks; 4 | using LQ1Bot.Interface; 5 | using Mirai.Net.Data.Messages.Receivers; 6 | using Mirai.Net.Sessions.Http.Managers; 7 | 8 | namespace LQ1Bot.Plugins { 9 | 10 | internal class Dice : PluginBase, IGroupMessage, IFriendMessage { 11 | public override int Priority => 9997; 12 | 13 | public override string PluginName => "Dice"; 14 | 15 | public override bool CanDisable => true; 16 | 17 | public async Task FriendMessage(FriendMessageReceiver e) { 18 | string text = Utils.GetMessageText(e.MessageChain); 19 | string q = e.Sender.Id; 20 | #region DICE 21 | if (Regex.IsMatch(text.ToLower().Trim(), @"^dice$|^dice \d+d\d+$")) { 22 | int count = 1; 23 | int max; 24 | if (text.ToLower().Trim() == "dice") { 25 | max = 6; 26 | } else { 27 | count = int.Parse(text.ToLower().Trim().Split(' ')[1].Split('d')[0]); 28 | max = int.Parse(text.ToLower().Trim().Split(' ')[1].Split('d')[1]); 29 | max = max < 1 ? 1 : max; 30 | count = count < 1 ? 1 : count; 31 | count = count > 10 ? 10 : count; 32 | } 33 | Random r = new Random(); 34 | string res = ""; 35 | for (int i = 0; i < count; i++) { 36 | if (i == 0) { 37 | res += r.Next(1, max + 1).ToString(); 38 | } else { 39 | res += "," + r.Next(1, max + 1).ToString(); 40 | } 41 | } 42 | await MessageManager.SendFriendMessageAsync(q, $"{e.Sender.NickName}投出了{res}!"); 43 | return true; 44 | } 45 | #endregion 46 | return false; 47 | } 48 | 49 | public async Task GroupMessage(GroupMessageReceiver e) { 50 | string text = Utils.GetMessageText(e.MessageChain); 51 | string q = e.Sender.Group.Id; 52 | #region DICE 53 | if (Regex.IsMatch(text.ToLower().Trim(), @"^dice$|^dice \d+d\d+$")) { 54 | int count = 1; 55 | int max; 56 | if (text.ToLower().Trim() == "dice") { 57 | max = 6; 58 | } else { 59 | count = int.Parse(text.ToLower().Trim().Split(' ')[1].Split('d')[0]); 60 | max = int.Parse(text.ToLower().Trim().Split(' ')[1].Split('d')[1]); 61 | max = max < 1 ? 1 : max; 62 | count = count < 1 ? 1 : count; 63 | count = count > 10 ? 10 : count; 64 | } 65 | Random r = new Random(); 66 | string res = ""; 67 | for (int i = 0; i < count; i++) { 68 | if (i == 0) { 69 | res += r.Next(1, max + 1).ToString(); 70 | } else { 71 | res += "," + r.Next(1, max + 1).ToString(); 72 | } 73 | } 74 | await MessageManager.SendGroupMessageAsync(q, $"{e.Sender.Name}投出了{res}!"); 75 | return true; 76 | } 77 | #endregion 78 | return false; 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/ExceptionGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using LQ1Bot.Interface; 5 | using Mirai.Net.Data.Messages.Receivers; 6 | using Mirai.Net.Sessions.Http.Managers; 7 | 8 | namespace LQ1Bot.Plugins { 9 | 10 | internal class ExceptionGenerator : PluginBase, IGroupMessage, IFriendMessage { 11 | public override int Priority => 9992; 12 | 13 | public override string PluginName => "ExceptionGenerator"; 14 | 15 | public override bool CanDisable => true; 16 | 17 | private readonly List ExceptionList = new List(); 18 | 19 | public ExceptionGenerator() { 20 | var err = new Exception(); 21 | Stack s = new Stack(); 22 | s.Push(err.GetType()); 23 | while (s.Count > 0) { 24 | var v = s.Pop(); 25 | var temp = Utils.GetSubClass(v); 26 | ExceptionList.AddRange(temp); 27 | temp.ForEach(o => s.Push(o)); 28 | } 29 | } 30 | 31 | public async Task FriendMessage(FriendMessageReceiver e) { 32 | switch (Utils.GetMessageText(e.MessageChain)) { 33 | #region 手动报错 34 | case "来点bug": 35 | case "来点异常": 36 | case "来点错误": 37 | case "来点exception": 38 | var ExceptionType = ExceptionList[(new Random()).Next(ExceptionList.Count)]; 39 | try { 40 | throw ((Exception) Activator.CreateInstance(ExceptionType)); 41 | } catch (Exception eee) { 42 | await MessageManager.SendFriendMessageAsync(e.Sender.Id, eee.ToString()); 43 | } 44 | return true; 45 | #endregion 46 | default: 47 | return false; 48 | } 49 | } 50 | 51 | public async Task GroupMessage(GroupMessageReceiver e) { 52 | switch (Utils.GetMessageText(e.MessageChain)) { 53 | #region 手动报错 54 | case "来点bug": 55 | case "来点异常": 56 | case "来点错误": 57 | case "来点exception": 58 | var ExceptionType = ExceptionList[(new Random()).Next(ExceptionList.Count)]; 59 | try { 60 | throw ((Exception) Activator.CreateInstance(ExceptionType)); 61 | } catch (Exception eee) { 62 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, eee.ToString()); 63 | } 64 | return true; 65 | #endregion 66 | default: 67 | return false; 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/FunctionSwitch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using LQ1Bot.Interface; 7 | using Mirai.Net.Data.Messages.Receivers; 8 | using Mirai.Net.Sessions.Http.Managers; 9 | using Newtonsoft.Json.Linq; 10 | 11 | namespace LQ1Bot.Plugins { 12 | 13 | internal class FunctionSwitch : PluginBase, IGroupMessage { 14 | public override int Priority => 15000; 15 | public override string PluginName => "FunctionSwitch"; 16 | 17 | public override bool CanDisable => false; 18 | 19 | public static Dictionary> Config = new Dictionary>(); 20 | 21 | private readonly HashSet Admins = new HashSet(); 22 | 23 | //TODO: 修复新插件设置不会被保存到已存在的配置文件里的问题 24 | public FunctionSwitch() { 25 | if (!Directory.Exists("plugincfg")) { 26 | Directory.CreateDirectory("plugincfg"); 27 | } 28 | 29 | foreach (var v in Directory.GetFiles("plugincfg")) { 30 | if (long.TryParse(v.Substring(0, v.IndexOf('.'))[10..], out long Group)) { 31 | var d = new Dictionary(); 32 | string json = File.ReadAllText(v); 33 | JObject o = JObject.Parse(json); 34 | foreach (var oo in o) { 35 | d.Add(oo.Key, bool.Parse(oo.Value.ToString())); 36 | } 37 | foreach (var Plugin in PluginController.PluginInstance) { 38 | if (Plugin.CanDisable && !o.ContainsKey(Plugin.PluginName)) { 39 | o.Add(Plugin.PluginName, true); 40 | d.Add(Plugin.PluginName, true); 41 | } 42 | } 43 | 44 | //if (Group == 569901561) { 45 | // MessageManager.SendGroupMessageAsync(Group.ToString(), o.ToString()); 46 | 47 | // string tmp = ""; 48 | // foreach (var Plugin in PluginController.PluginInstance.OrderByDescending(o => o.Priority)) { 49 | // tmp += $"[{Plugin.Priority}]\t{Plugin.PluginName}\n"; 50 | // } 51 | // //MessageManager.SendGroupMessageAsync(Group.ToString(), tmp); 52 | //} 53 | //foreach (var Plugin in PluginController.PluginInstance.OrderByDescending(o => o.Priority)) { 54 | // if (Plugin.CanDisable) { 55 | // if (!d.ContainsKey(Plugin.PluginName)) { 56 | // d.Add(Plugin.PluginName, true); 57 | // Console.WriteLine(Plugin.PluginName); 58 | // Console.WriteLine(d.ContainsKey(Plugin.PluginName)); 59 | // } 60 | // } 61 | //} 62 | Config.Add(Group, d); 63 | } 64 | } 65 | if (File.Exists("plugincfg/admin.txt")) { 66 | try { 67 | foreach (string v2 in File.ReadAllText("plugincfg/admin.txt").Split("|")) { 68 | Admins.Add(long.Parse(v2)); 69 | } 70 | } catch (Exception) { 71 | } 72 | } else { 73 | File.Create("plugincfg/admin.txt"); 74 | } 75 | } 76 | 77 | public async Task GroupMessage(GroupMessageReceiver e) { 78 | string text = Utils.GetMessageText(e.MessageChain); 79 | if (text == "!createconfig" && (e.Sender.Permission != Mirai.Net.Data.Shared.Permissions.Member || Admins.Contains(long.Parse(e.Sender.Id)))) { 80 | JObject o = new JObject(); 81 | Config.Remove(long.Parse(e.Sender.Group.Id)); 82 | var d = new Dictionary(); 83 | foreach (var Plugin in PluginController.PluginInstance) { 84 | if (Plugin.CanDisable) { 85 | o.Add(Plugin.PluginName, true); 86 | d.Add(Plugin.PluginName, true); 87 | } 88 | } 89 | Config.Add(long.Parse(e.Sender.Group.Id), d); 90 | File.WriteAllText("plugincfg/" + e.Sender.Group.Id + ".json", o.ToString()); 91 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "已创建配置文件"); 92 | return true; 93 | } 94 | if (text.StartsWith("!query ")) { 95 | var Name = text[7..]; 96 | if (Config.TryGetValue(long.Parse(e.Sender.Group.Id), out Dictionary cfg)) { 97 | if (cfg.ContainsKey(Name)) { 98 | if (cfg.GetValueOrDefault(Name)) { 99 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "该功能已启用"); 100 | } else { 101 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "该功能已禁用"); 102 | } 103 | } else { 104 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "未发现该功能"); 105 | } 106 | } else { 107 | InitGroup(long.Parse(e.Sender.Group.Id)); 108 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "该功能已启用"); 109 | } 110 | return true; 111 | } 112 | if (text.StartsWith("!enable ") && (e.Sender.Permission != Mirai.Net.Data.Shared.Permissions.Member || Admins.Contains(long.Parse(e.Sender.Id)))) { 113 | var Name = text[8..]; 114 | if (Config.TryGetValue(long.Parse(e.Sender.Group.Id), out Dictionary cfg)) { 115 | if (cfg.ContainsKey(Name)) { 116 | cfg.Remove(Name); 117 | cfg.Add(Name, true); 118 | Save(long.Parse(e.Sender.Group.Id)); 119 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "已启用" + Name); 120 | } else { 121 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "未发现该功能"); 122 | } 123 | } else { 124 | InitGroup(long.Parse(e.Sender.Group.Id)); 125 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "已启用" + Name); 126 | } 127 | return true; 128 | } 129 | if (text.StartsWith("!disable ") && (e.Sender.Permission != Mirai.Net.Data.Shared.Permissions.Member || Admins.Contains(long.Parse(e.Sender.Id)))) { 130 | var Name = text[9..]; 131 | if (Config.TryGetValue(long.Parse(e.Sender.Group.Id), out Dictionary cfg)) { 132 | if (cfg.ContainsKey(Name)) { 133 | cfg.Remove(Name); 134 | cfg.Add(Name, false); 135 | Save(long.Parse(e.Sender.Group.Id)); 136 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "已禁用" + Name); 137 | } else { 138 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "未发现该功能"); 139 | } 140 | } else { 141 | InitGroup(long.Parse(e.Sender.Group.Id)); 142 | cfg = Config.GetValueOrDefault(long.Parse(e.Sender.Group.Id)); 143 | cfg.Remove(Name); 144 | cfg.Add(Name, false); 145 | Save(long.Parse(e.Sender.Group.Id)); 146 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "已禁用" + Name); 147 | } 148 | return true; 149 | } 150 | if (text == "!plugins") { 151 | List Enabled = new List(); 152 | List Disabled = new List(); 153 | if (Config.TryGetValue(long.Parse(e.Sender.Group.Id), out Dictionary cfg)) { 154 | foreach (var v in cfg) { 155 | if (v.Value) { 156 | Enabled.Add(v.Key); 157 | } else { 158 | Disabled.Add(v.Key); 159 | } 160 | } 161 | } else { 162 | InitGroup(long.Parse(e.Sender.Group.Id)); 163 | cfg = Config.GetValueOrDefault(long.Parse(e.Sender.Group.Id)); 164 | foreach (var v in cfg) { 165 | Enabled.Add(v.Key); 166 | } 167 | } 168 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "所有可用插件\n已启用:" + (Enabled.Count == 0 ? "无" : string.Join(" ", Enabled)) + "\n已禁用:" + (Disabled.Count == 0 ? "无" : string.Join(" ", Disabled))); 169 | return true; 170 | } 171 | return false; 172 | } 173 | 174 | public static bool IsEnabled(long Group, string Name) { 175 | if (Config.TryGetValue(Group, out Dictionary cfg)) { 176 | if (cfg.TryGetValue(Name, out bool enabled)) { 177 | return enabled; 178 | } else { 179 | return false; 180 | } 181 | } else { 182 | return true; 183 | } 184 | } 185 | 186 | private void Save(long Group) { 187 | if (Config.TryGetValue(Group, out Dictionary cfg)) { 188 | JObject o = new JObject(); 189 | foreach (var c in cfg) { 190 | o.Add(c.Key, c.Value); 191 | } 192 | File.WriteAllText("plugincfg/" + Group + ".json", o.ToString()); 193 | } else { 194 | InitGroup(Group); 195 | cfg = Config.GetValueOrDefault(Group); 196 | JObject o = new JObject(); 197 | foreach (var c in cfg) { 198 | o.Add(c.Key, c.Value); 199 | } 200 | File.WriteAllText("plugincfg/" + Group + ".json", o.ToString()); 201 | } 202 | } 203 | 204 | private void InitGroup(long Group) { 205 | Config.Remove(Group); 206 | var d = new Dictionary(); 207 | foreach (var Plugin in PluginController.PluginInstance) { 208 | if (Plugin.CanDisable) { 209 | d.Add(Plugin.PluginName, true); 210 | } 211 | } 212 | Config.Add(Group, d); 213 | } 214 | } 215 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/Hitokoto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | using System.Threading.Tasks; 5 | using LQ1Bot.Interface; 6 | using Mirai.Net.Data.Messages.Receivers; 7 | using Mirai.Net.Sessions.Http.Managers; 8 | using Newtonsoft.Json.Linq; 9 | 10 | namespace LQ1Bot.Plugins { 11 | 12 | internal class Hitokoto : PluginBase, IGroupMessage, IFriendMessage { 13 | public override int Priority => 9994; 14 | 15 | public override string PluginName => "Hitokoto"; 16 | public override bool CanDisable => true; 17 | 18 | public async Task FriendMessage(FriendMessageReceiver e) { 19 | #region 一言 20 | if (Utils.GetMessageText(e.MessageChain) == "一言") { 21 | Console.ForegroundColor = ConsoleColor.Green; 22 | Console.WriteLine("一言"); 23 | Console.ResetColor(); 24 | string result = ""; 25 | HttpWebRequest req = (HttpWebRequest) WebRequest.Create(@"https://v1.hitokoto.cn/"); 26 | req.Timeout = 3000; 27 | try { 28 | HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); 29 | Stream stream = resp.GetResponseStream(); 30 | using (StreamReader reader = new StreamReader(stream)) { 31 | result = reader.ReadToEnd(); 32 | } 33 | stream.Close(); 34 | } catch (Exception) { } 35 | JObject jj = JObject.Parse(result); 36 | string msg = jj["hitokoto"]?.ToString(); 37 | string from = jj["from_who"]?.ToString(); 38 | if (from != null && from != "" && from != "null") 39 | await MessageManager.SendFriendMessageAsync(e.Sender.Id,$"{msg}\t——{from}"); 40 | else 41 | await MessageManager.SendFriendMessageAsync(e.Sender.Id, $"{msg}"); 42 | return true; 43 | } 44 | #endregion 45 | return false; 46 | } 47 | 48 | public async Task GroupMessage(GroupMessageReceiver e) { 49 | #region 一言 50 | if (Utils.GetMessageText(e.MessageChain) == "一言") { 51 | Console.ForegroundColor = ConsoleColor.Green; 52 | Console.WriteLine("一言"); 53 | Console.ResetColor(); 54 | string result = ""; 55 | HttpWebRequest req = (HttpWebRequest) WebRequest.Create(@"https://v1.hitokoto.cn/"); 56 | req.Timeout = 3000; 57 | try { 58 | HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); 59 | Stream stream = resp.GetResponseStream(); 60 | using (StreamReader reader = new StreamReader(stream)) { 61 | result = reader.ReadToEnd(); 62 | } 63 | stream.Close(); 64 | } catch (Exception) { } 65 | JObject jj = JObject.Parse(result); 66 | string msg = jj["hitokoto"]?.ToString(); 67 | string from = jj["from_who"]?.ToString(); 68 | if (from != null && from != "" && from != "null") 69 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, $"{msg}\t——{from}"); 70 | else 71 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, $"{msg}"); 72 | return true; 73 | } 74 | #endregion 75 | return false; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/HomoCalc.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | using LQ1Bot.Interface; 6 | using Mirai.Net.Data.Messages.Receivers; 7 | using Mirai.Net.Sessions.Http.Managers; 8 | 9 | namespace LQ1Bot.Plugins { 10 | class HomoCalc : PluginBase, IGroupMessage,IFriendMessage { 11 | public override int Priority => 9986; 12 | 13 | public override string PluginName => "HomoCalc"; 14 | 15 | public override bool CanDisable => true; 16 | 17 | private readonly Dictionary BinSet = new Dictionary() { 18 | {1073741824,"114514*((1+1)*4514+(11*(45-14)+(11-4+5-1-4)))+(11*4514+(114*5*14+(-(1-14)*5*14+(11-4-5+14))))" }, 19 | {536870912,"114514*((1145+1)*4+(114-5-1-4))+(114*51*4+(114*51+4+(11*4*5-14)))" }, 20 | {268435456,"114514*(114*5*1*4+(11*4+5*1*4))+(1+14514+(-1-14*(5-14)))" }, 21 | {134217728,"114514*(1145+14+(1*14-5/1+4))+(1+14*514+(114-5+14))" }, 22 | {67108864,"114514*(114*5+14+(-11+4-5+14))+((1+1)*451*4+(11+45/1-4))" }, 23 | {33554432,"114514*(11+4*5*14+(-11+4-5+14))+(114*(5-1)*4+(1-14+5+14))" }, 24 | {16777216,"114514*(11+45*(-(1-4)))+(11*4514+(114*5*14+(1+14+514+(11-4+5+1-4))))" }, 25 | {8388608,"114514*(1*14*5-1+4)+(114*51*4+(114*51+4+(-11+4+5+14)))" }, 26 | {4194304,"114514*(11+4*5+1+4)+(114*514+(11451+4+(114*(-5)*(1-4)+(-11+45+1+4))))" }, 27 | {2097152,"114514*(1+1+4*5*1-4)+(114*51*4+(11451+4+(1145+14+(1*(-1)+45-14))))" }, 28 | {1048576,"114514*(11-4+5+1-4)+(1145*14+((11+451)*4+(-1-1+4+5*14)))" }, 29 | {524288,"114514*(-11-4+5+14)+(114*514+(1+14*514+((1+145)*(-(1-4))+(11/(45-1)*4))))" }, 30 | {262144,"114514*(-11+4-5+14)+(114*51*4+((1+1)*4514+(11+4*51*4+(11-4*5+14))))" }, 31 | {131072,"114514+(1145*14+(1*14+514))" }, 32 | {65536,"114*514+(11*45*14+(-11/4+51/4))" }, 33 | {32768,"114*51*4+((1+1)*4514+(11*45-14+(11*(-4)+51-4)))" }, 34 | {16384,"1145*14+((11-4)*51-4+(11/(45-1)*4))" }, 35 | {8192,"114*5*14+((1+1)*4+51*4)" }, 36 | {4096,"(1+1)*451*4+(11*(45-1)+4)" }, 37 | {2048,"-11+4*514+(11*(-4)+51-4)" }, 38 | {1024,"1*(1+4)*51*4+(-11-4+5+14)" }, 39 | {512,"1+1-4+514" }, 40 | {256,"(114-51)*4+(-11-4+5+14)" }, 41 | {128,"1+1+(4+5)*14" }, 42 | {64,"1-1+4*(5-1)*4" }, 43 | {32,"1+1*45-14" }, 44 | {16,"1+1+4+5+1+4" }, 45 | {8,"1+1+4+5+1-4" }, 46 | {4,"1+1+4-5-1+4" }, 47 | {2,"(-1)*(1+(4+5)/(1-4))" }, 48 | {1,"1+1*4*(5-1-4)" }, 49 | }; 50 | 51 | //这么屑的算法有什么存在的必要吗 52 | //现在这生成的算式又臭又长 53 | //之后再考虑该怎么优化 54 | private string Num2Homo(int n) { 55 | if (n == 0) 56 | return "1+1-4+5+1-4"; 57 | if (n == -2147483648) 58 | return "-114514*(1145*14+((1-14)*51*(-4)+((1+14)*5-1*4)))+(1*(1+4)*514+(11+4*5+1+4))"; 59 | bool isNegative = false; 60 | if (n < 0) { 61 | isNegative = true; 62 | n = -n; 63 | } 64 | List nums = new List(); 65 | while (n != 0) { 66 | foreach (var v in BinSet) { 67 | if (v.Key <= n) { 68 | nums.Add(BinSet.GetValueOrDefault(v.Key)); 69 | n -= v.Key; 70 | break; 71 | } 72 | } 73 | } 74 | if (isNegative) 75 | return $"-({string.Join("+", nums)})"; 76 | else 77 | return $"{string.Join("+", nums)}"; 78 | } 79 | 80 | public async Task FriendMessage(FriendMessageReceiver e) { 81 | string text = Utils.GetMessageText(e.MessageChain); 82 | string q = e.FriendId; 83 | 84 | if (text.StartsWith("恶臭论证 ")) { 85 | text = text[5..]; 86 | if (int.TryParse(text, out int num)) { 87 | await MessageManager.SendFriendMessageAsync(q, num + " = " + Num2Homo(num)); 88 | } else { 89 | await MessageManager.SendFriendMessageAsync(q, "在?你管这叫int32整数?"); 90 | } 91 | return true; 92 | } 93 | return false; 94 | } 95 | 96 | public async Task GroupMessage(GroupMessageReceiver e) { 97 | string text = Utils.GetMessageText(e.MessageChain); 98 | string q = e.Sender.Group.Id; 99 | 100 | if (text.StartsWith("恶臭论证 ")) { 101 | text = text[5..]; 102 | if (int.TryParse(text, out int num)) { 103 | await MessageManager.SendGroupMessageAsync(q, num + " = " + Num2Homo(num)); 104 | } else { 105 | await MessageManager.SendGroupMessageAsync(q, "在?你管这叫int32整数?"); 106 | } 107 | return true; 108 | } 109 | return false; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /LQ1Bot/Plugins/KusaRecorder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using System.Threading.Tasks; 4 | using LQ1Bot.Interface; 5 | using Microsoft.Data.Sqlite; 6 | using Mirai.Net.Data.Messages.Receivers; 7 | using Mirai.Net.Sessions.Http.Managers; 8 | 9 | namespace LQ1Bot.Plugins { 10 | 11 | internal class KusaRecorder : PluginBase, IGroupMessage { 12 | public override int Priority => 9999; 13 | 14 | public override string PluginName => "KusaRecorder"; 15 | public override bool CanDisable => true; 16 | 17 | public async Task GroupMessage(GroupMessageReceiver e) { 18 | string text = Utils.GetMessageText(e.MessageChain); 19 | string q = e.Sender.Group.Id; 20 | #region 生草榜查询 21 | switch (text) { 22 | #region 今日生草榜读取 23 | case "今日除草剂": 24 | case "今日生草榜": 25 | case "今日生草机": 26 | case "今日百草枯": 27 | try { 28 | using SqliteConnection conn = new SqliteConnection("Data Source=chat.db"); 29 | conn.Open(); 30 | SqliteCommand cmd = new SqliteCommand("", conn) { 31 | CommandText = "select name,count(*) from main where time>=date('now','localtime') and type='cao' and fromgroup=" + q + " group by qq order by count(*) desc limit 10" 32 | }; 33 | SqliteDataReader dr = cmd.ExecuteReader(); 34 | 35 | string rep = "今日生草榜前10名\r"; 36 | string list = ""; 37 | while (dr.Read()) { 38 | list += dr["name"] + " 生草数:" + dr["count(*)"] + "\r"; 39 | } 40 | dr.Close(); 41 | 42 | if (list != "") { 43 | await MessageManager.SendGroupMessageAsync(q, rep + list); 44 | } else { 45 | await MessageManager.SendGroupMessageAsync(q, "今天还没人发草!"); 46 | } 47 | } catch (Exception ee) { 48 | Console.ForegroundColor = ConsoleColor.Red; 49 | Console.WriteLine("读取生草榜出现错误\n" + ee.Message); 50 | Console.ResetColor(); 51 | } 52 | return true; 53 | #endregion 54 | #region 昨日生草榜读取 55 | case "昨日除草剂": 56 | case "昨日生草榜": 57 | case "昨日生草机": 58 | case "昨日百草枯": 59 | try { 60 | using SqliteConnection conn = new SqliteConnection("Data Source=chat.db"); 61 | conn.Open(); 62 | SqliteCommand cmd = new SqliteCommand("", conn) { 63 | CommandText = "select name,count(*) from main where time=date('now','-1 day','localtime') and type='cao' and fromgroup=" + q + " group by qq order by count(*) desc limit 10" 64 | }; 65 | SqliteDataReader dr = cmd.ExecuteReader(); 66 | 67 | string rep = "昨日生草榜前10名\r"; 68 | string list = ""; 69 | while (dr.Read()) { 70 | list += dr["name"] + " 生草数:" + dr["count(*)"] + "\r"; 71 | } 72 | dr.Close(); 73 | 74 | if (list != "") { 75 | await MessageManager.SendGroupMessageAsync(q, rep + list); 76 | } else { 77 | await MessageManager.SendGroupMessageAsync(q, "昨天没人发草!"); 78 | } 79 | } catch (Exception ee) { 80 | Console.ForegroundColor = ConsoleColor.Red; 81 | Console.WriteLine("读取生草榜出现错误\n" + ee.Message); 82 | Console.ResetColor(); 83 | } 84 | return true; 85 | #endregion 86 | #region 生草榜读取 87 | case "除草剂": 88 | case "生草榜": 89 | case "生草机": 90 | case "百草枯": 91 | try { 92 | using SqliteConnection conn = new SqliteConnection("Data Source=chat.db"); 93 | conn.Open(); 94 | SqliteCommand cmd = new SqliteCommand("", conn) { 95 | CommandText = "select name,count(*) from main where type='cao' and fromgroup=" + q + " group by qq order by count(*) desc limit 10" 96 | }; 97 | SqliteDataReader dr = cmd.ExecuteReader(); 98 | 99 | string rep = "生草榜前10名\r"; 100 | string list = ""; 101 | while (dr.Read()) { 102 | list += dr["name"] + " 生草数:" + dr["count(*)"] + "\r"; 103 | } 104 | dr.Close(); 105 | 106 | if (list != "") { 107 | await MessageManager.SendGroupMessageAsync(q, rep + list); 108 | } else { 109 | await MessageManager.SendGroupMessageAsync(q, "目前无人发草!"); 110 | } 111 | } catch (Exception ee) { 112 | Console.ForegroundColor = ConsoleColor.Red; 113 | Console.WriteLine("读取生草榜出现错误\n" + ee.Message); 114 | Console.ResetColor(); 115 | } 116 | return true; 117 | #endregion 118 | #region 今日生草榜总榜读取 119 | case "今日除草剂总榜": 120 | case "今日生草榜总榜": 121 | case "今日生草机总榜": 122 | case "今日百草枯总榜": 123 | try { 124 | using SqliteConnection conn = new SqliteConnection("Data Source=chat.db"); 125 | conn.Open(); 126 | SqliteCommand cmd = new SqliteCommand("", conn) { 127 | CommandText = "select name,count(*) from main where time>=date('now','localtime') and type='cao' group by qq order by count(*) desc limit 10" 128 | }; 129 | SqliteDataReader dr = cmd.ExecuteReader(); 130 | 131 | string rep = "今日生草榜全群总榜前10名\r"; 132 | string list = ""; 133 | while (dr.Read()) { 134 | list += dr["name"] + " 生草数:" + dr["count(*)"] + "\r"; 135 | } 136 | dr.Close(); 137 | 138 | if (list != "") { 139 | await MessageManager.SendGroupMessageAsync(q, rep + list); 140 | } else { 141 | await MessageManager.SendGroupMessageAsync(q, "今天还没人发草!"); 142 | } 143 | } catch (Exception ee) { 144 | Console.ForegroundColor = ConsoleColor.Red; 145 | Console.WriteLine("读取生草榜出现错误\n" + ee.Message); 146 | Console.ResetColor(); 147 | } 148 | return true; 149 | #endregion 150 | #region 昨日生草榜总榜读取 151 | case "昨日除草剂总榜": 152 | case "昨日生草榜总榜": 153 | case "昨日生草机总榜": 154 | case "昨日百草枯总榜": 155 | try { 156 | using SqliteConnection conn = new SqliteConnection("Data Source=chat.db"); 157 | conn.Open(); 158 | SqliteCommand cmd = new SqliteCommand("", conn) { 159 | CommandText = "select name,count(*) from main where time=date('now','-1 day','localtime') and type='cao' group by qq order by count(*) desc limit 10" 160 | }; 161 | SqliteDataReader dr = cmd.ExecuteReader(); 162 | 163 | string rep = "昨日生草榜全群总榜前10名\r"; 164 | string list = ""; 165 | while (dr.Read()) { 166 | list += dr["name"] + " 生草数:" + dr["count(*)"] + "\r"; 167 | } 168 | dr.Close(); 169 | 170 | if (list != "") { 171 | await MessageManager.SendGroupMessageAsync(q, rep + list); 172 | } else { 173 | await MessageManager.SendGroupMessageAsync(q, "昨天没人发草!"); 174 | } 175 | } catch (Exception ee) { 176 | Console.ForegroundColor = ConsoleColor.Red; 177 | Console.WriteLine("读取生草榜出现错误\n" + ee.Message); 178 | Console.ResetColor(); 179 | } 180 | return true; 181 | #endregion 182 | #region 生草榜总榜读取 183 | case "除草剂总榜": 184 | case "生草榜总榜": 185 | case "生草机总榜": 186 | case "百草枯总榜": 187 | try { 188 | using SqliteConnection conn = new SqliteConnection("Data Source=chat.db"); 189 | conn.Open(); 190 | SqliteCommand cmd = new SqliteCommand("", conn) { 191 | CommandText = "select name,count(*) from main where type='cao' group by qq order by count(*) desc limit 10" 192 | }; 193 | SqliteDataReader dr = cmd.ExecuteReader(); 194 | 195 | string rep = "生草榜全群总榜前10名\r"; 196 | string list = ""; 197 | while (dr.Read()) { 198 | list += dr["name"] + " 生草数:" + dr["count(*)"] + "\r"; 199 | } 200 | dr.Close(); 201 | 202 | if (list != "") { 203 | await MessageManager.SendGroupMessageAsync(q, rep + list); 204 | } else { 205 | await MessageManager.SendGroupMessageAsync(q, "目前无人发草!"); 206 | } 207 | } catch (Exception ee) { 208 | Console.ForegroundColor = ConsoleColor.Red; 209 | Console.WriteLine("读取生草榜出现错误\n" + ee.Message); 210 | Console.ResetColor(); 211 | } 212 | return true; 213 | #endregion 214 | } 215 | #endregion 216 | #region 生草记录 217 | if (Regex.IsMatch(text.ToLower(), @"[草艸艹🌿]|w{3,}|kusa|cao|grass]")) { 218 | Console.WriteLine("草"); 219 | try { 220 | SqliteConnection conn = new SqliteConnection("Data Source=chat.db"); 221 | conn.Open(); 222 | SqliteCommand cmd = new SqliteCommand("", conn); 223 | SqliteDataReader dr; 224 | cmd.CommandText = "select count(*) from main where qq=" + e.Sender.Id + " and time>=datetime('now','localtime','-1 minutes') and type='cao' and fromgroup=" + q; 225 | dr = cmd.ExecuteReader(); 226 | 227 | int count = 0; 228 | while (dr.Read()) { 229 | count = int.Parse(dr["count(*)"].ToString()); 230 | } 231 | 232 | Console.WriteLine("一分钟内生草次数:\t" + count.ToString()); 233 | Console.ResetColor(); 234 | 235 | if (count >= 7) { 236 | await GroupManager.MuteAsync(e.Sender.Id, q, TimeSpan.FromMinutes(3.0)); 237 | Console.ForegroundColor = ConsoleColor.DarkYellow; 238 | Console.WriteLine("已禁言用户"); 239 | Console.ResetColor(); 240 | await MessageManager.SendGroupMessageAsync(q, "禁止刷屏"); 241 | } else { 242 | cmd = new SqliteCommand("", conn) { 243 | CommandText = $"insert into main values (strftime('%Y-%m-%d %H:%M:%f','now','localtime'),@nickname,{e.Sender.Id},{q},'cao')" 244 | }; 245 | cmd.Parameters.AddWithValue("@nickname", e.Sender.Name); 246 | 247 | dr = cmd.ExecuteReader(); 248 | dr.Close(); 249 | Console.ForegroundColor = ConsoleColor.DarkGreen; 250 | Console.WriteLine("成功写入草,用户名:\t" + e.Sender.Name); 251 | } 252 | dr.Close(); 253 | conn.Close(); 254 | } catch (Exception ee) { 255 | Console.ForegroundColor = ConsoleColor.Red; 256 | Console.WriteLine("写入数据库出现错误\n" + ee.Message); 257 | Console.ResetColor(); 258 | } 259 | return false; 260 | } 261 | #endregion 262 | return false; 263 | } 264 | } 265 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/LiveNotify.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text.Json; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using Flurl.Http; 8 | using LQ1Bot.Interface; 9 | using Mirai.Net.Data.Messages.Concretes; 10 | using Mirai.Net.Data.Messages.Receivers; 11 | using Mirai.Net.Sessions.Http.Managers; 12 | using Mirai.Net.Utils.Scaffolds; 13 | using Newtonsoft.Json.Linq; 14 | 15 | namespace LQ1Bot.Plugins { 16 | 17 | internal class LiveNotify : PluginBase, IGroupMessage { 18 | public override int Priority => 9979; 19 | 20 | public override string PluginName => "LiveNotify"; 21 | 22 | public override bool CanDisable => true; 23 | 24 | private readonly Dictionary> UidBind = new(); 25 | private readonly Dictionary LastLiveTime = new(); 26 | 27 | private const int cooldown = 30; //冷却时间(s) 28 | 29 | public LiveNotify() { 30 | try { 31 | string uid = File.ReadAllText("livecfg/uidbind.json"); 32 | string livetime = File.ReadAllText("livecfg/lastlivetime.json"); 33 | 34 | var temp = JsonSerializer.Deserialize>>(uid); 35 | foreach (var v in temp) { 36 | UidBind.Add(long.Parse(v.Key), v.Value); 37 | } 38 | LastLiveTime = JsonSerializer.Deserialize>(livetime); 39 | } catch (Exception ex) { 40 | File.WriteAllText("livecfg/uidbind.json", "{}"); 41 | File.WriteAllText("livecfg/lastlivetime.json", "{}"); 42 | Console.WriteLine(ex); 43 | } 44 | (new Thread(new ThreadStart(async () => { 45 | while (true) { 46 | Thread.Sleep(1000 * cooldown); 47 | await NotifyLive(); 48 | } 49 | }))).Start(); 50 | } 51 | public async Task GroupMessage(GroupMessageReceiver e) { 52 | string text = Utils.GetMessageText(e.MessageChain); 53 | string q = e.Sender.Group.Id; 54 | if (text.StartsWith("!subscribe ") && PermissionMgr.IsGroupOrBotAdmin(e.Sender)) { 55 | if (long.TryParse(text[11..], out long mid)) { 56 | if (UidBind.TryGetValue(mid, out var groups)) { 57 | if (!groups.Contains(long.Parse(q))) { 58 | groups.Add(long.Parse(q)); 59 | UidBind.Remove(mid); 60 | UidBind.Add(mid, groups); 61 | 62 | File.WriteAllText("livecfg/uidbind.json", JsonSerializer.Serialize(UidBind)); 63 | await MessageManager.SendGroupMessageAsync(q, "成功添加关注!"); 64 | } else { 65 | await MessageManager.SendGroupMessageAsync(q, "已关注该主播!"); 66 | } 67 | } else { 68 | UidBind.Add(mid, new HashSet() { long.Parse(q) }); 69 | File.WriteAllText("livecfg/uidbind.json", JsonSerializer.Serialize(UidBind)); 70 | await MessageManager.SendGroupMessageAsync(q, "成功添加关注!"); 71 | } 72 | } 73 | return true; 74 | } 75 | if (text.StartsWith("!unsubscribe ") && PermissionMgr.IsGroupOrBotAdmin(e.Sender)) { 76 | if (long.TryParse(text[13..], out long mid)) { 77 | if (UidBind.TryGetValue(mid, out var groups)) { 78 | if (groups.Contains(long.Parse(q))) { 79 | groups.Remove(long.Parse(q)); 80 | UidBind.Remove(mid); 81 | if (groups.Count != 0) { 82 | UidBind.Add(mid, groups); 83 | } 84 | File.WriteAllText("livecfg/uidbind.json", JsonSerializer.Serialize(UidBind)); 85 | await MessageManager.SendGroupMessageAsync(q, "成功取消关注!"); 86 | } else { 87 | await MessageManager.SendGroupMessageAsync(q, "未关注该主播!"); 88 | } 89 | } else { 90 | await MessageManager.SendGroupMessageAsync(q, "未关注该主播!"); 91 | } 92 | } 93 | return true; 94 | } 95 | if (text == "!showsubscribe") { 96 | List result = new(); 97 | foreach (var v in UidBind) { 98 | if (v.Value.Contains(long.Parse(q))) { 99 | result.Add(v.Key); 100 | } 101 | } 102 | if (result.Count > 0) { 103 | await MessageManager.SendGroupMessageAsync(q, "本群关注的主播uid:" + string.Join(", ", result)); 104 | } else { 105 | await MessageManager.SendGroupMessageAsync(q, "本群还未关注任何主播!"); 106 | } 107 | } 108 | return false; 109 | } 110 | 111 | private async Task NotifyLive() { 112 | try { 113 | string json = await $"https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids?rnd={new Random().Next()}" 114 | .PostJsonAsync(new { uids = UidBind.Keys }) 115 | .ReceiveString(); 116 | JObject data = JObject.Parse(json); 117 | if (data["code"].ToObject() == 0) { 118 | JObject livedata = (JObject) data["data"]; 119 | foreach (var v in livedata.Properties()) { 120 | long mid = long.Parse(v.Name); 121 | long lastlive = v.Value["live_time"].ToObject(); //上次直播时间 122 | int livestatus = v.Value["live_status"].ToObject(); //是否开播 123 | 124 | string username = v.Value["uname"].ToString(); 125 | string roomid = v.Value["room_id"].ToString(); 126 | string title = v.Value["title"].ToString(); 127 | string cover = v.Value["cover_from_user"].ToString(); 128 | 129 | if (livestatus == 1 && 130 | lastlive > LastLiveTime.GetValueOrDefault(mid, 1) && 131 | UidBind.TryGetValue(mid, out var val)) { 132 | 133 | LastLiveTime.Remove(mid); 134 | LastLiveTime.Add(mid, lastlive); 135 | File.WriteAllText("livecfg/lastlivetime.json", JsonSerializer.Serialize(LastLiveTime)); 136 | 137 | 138 | foreach (var group in val) { 139 | try { 140 | await MessageManager.SendGroupMessageAsync(group.ToString(), new MessageChainBuilder() 141 | .Append(new PlainMessage($"{username}开播了!\n{title}\nhttps://live.bilibili.com/{roomid}")) 142 | .Append(new ImageMessage() { Url = cover }) 143 | .Build()); 144 | Thread.Sleep(1000); 145 | } catch { } 146 | } 147 | } else if (livestatus != 1 && LastLiveTime.GetValueOrDefault(mid, 0) > 1) { 148 | var groups = UidBind.GetValueOrDefault(mid); 149 | LastLiveTime.Remove(mid); 150 | File.WriteAllText("livecfg/lastlivetime.json", JsonSerializer.Serialize(LastLiveTime)); 151 | foreach (var group in groups) { 152 | try { 153 | await MessageManager.SendGroupMessageAsync(group.ToString(), $"{username}下播了!"); 154 | Thread.Sleep(1000); 155 | } catch { } 156 | } 157 | } 158 | } 159 | } else { 160 | Console.Error.WriteLine(JsonSerializer.Serialize(data)); 161 | Thread.Sleep(5 * 60 * 1000); 162 | } 163 | } catch (Exception ee) { 164 | Console.Error.WriteLine(ee.Message); 165 | } 166 | } 167 | } 168 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/LivePrompt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | using System.Net.Http; 5 | using System.Text; 6 | using System.Text.RegularExpressions; 7 | using System.Threading.Tasks; 8 | using System.Web; 9 | using LQ1Bot.Interface; 10 | using Mirai.Net.Data.Messages.Receivers; 11 | using Mirai.Net.Sessions.Http.Managers; 12 | using Newtonsoft.Json; 13 | using Newtonsoft.Json.Linq; 14 | 15 | namespace LQ1Bot.Plugins { 16 | 17 | internal class LivePrompt : PluginBase, IGroupMessage { 18 | public override int Priority => 9981; 19 | 20 | public override string PluginName => "LivePrompt"; 21 | 22 | public override bool CanDisable => true; 23 | 24 | 25 | public async Task GroupMessage(GroupMessageReceiver e) { 26 | string text = Utils.GetMessageText(e.MessageChain); 27 | string q = e.Sender.Group.Id; 28 | 29 | if (text == "查询主播状态") { 30 | Init(q); 31 | try { 32 | Init(q); 33 | string temp = File.ReadAllText($"livepromptcfg/{q}.txt"); 34 | 35 | string uid = temp.Split("|")[0]; 36 | string content = temp.Split("|")[1]; 37 | 38 | var Now = DateTime.Now; 39 | 40 | WebClient client = new WebClient(); 41 | var obj = JObject.Parse(client.DownloadString("https://api.vtbs.moe/v1/detail/" + uid)); 42 | 43 | if (obj["liveStatus"].ToObject() == true) { 44 | await MessageManager.SendGroupMessageAsync(q, $"{obj["uname"]}正在直播!\nhttps://live.bilibili.com/{obj["roomid"]}"); 45 | } else { 46 | var LastLiveTime = new DateTime(1970, 1, 1).AddTicks(obj["lastLive"]["time"].ToObject() * 10000); 47 | 48 | var Diff = Now - LastLiveTime; 49 | string DiffStr = $"{Diff.Days}天{Diff.Hours}小时{Diff.Minutes}分{Diff.Seconds}秒{Diff.Ticks % 10000000 / 10000}毫秒{Diff.Ticks % 10000 / 10}微秒{Diff.Ticks % 10}00纳秒"; 50 | await MessageManager.SendGroupMessageAsync(q, content.Replace("{time}", DiffStr).Replace("{name}", obj["uname"].ToString())); 51 | } 52 | } catch (Exception ex) { 53 | Console.WriteLine(ex); 54 | await MessageManager.SendGroupMessageAsync(q, "查询开播状态出错"); 55 | } 56 | } 57 | return false; 58 | } 59 | 60 | private void Init(string q) { 61 | if (!File.Exists($"livepromptcfg/{q}.txt")) { 62 | if (!Directory.Exists("livepromptcfg")) { 63 | Directory.CreateDirectory("livepromptcfg"); 64 | } 65 | File.Create($"livepromptcfg/{q}.txt"); 66 | } 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/MsgInform.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using LQ1Bot.Interface; 5 | using Mirai.Net.Data.Messages.Receivers; 6 | 7 | namespace LQ1Bot.Plugins { 8 | 9 | internal class MsgInform : PluginBase, IGroupMessage, IFriendMessage, ITempMessage { 10 | public override int Priority => 99999; 11 | 12 | public override string PluginName => "MsgInform"; 13 | public override bool CanDisable => false; 14 | 15 | public async Task FriendMessage(FriendMessageReceiver e) { 16 | string q = e.Sender.Id; 17 | Console.ForegroundColor = ConsoleColor.Green; 18 | Console.WriteLine($"FriendMessage\t{e.Sender.NickName}({q})"); 19 | Console.ResetColor(); 20 | Console.WriteLine($"User:\t\t{e.Sender.NickName}[{e.Sender.Id}]\nContent:\t{Utils.GetMessageText(e.MessageChain)}"); 21 | string text = Utils.GetMessageText(e.MessageChain).Trim(); 22 | Console.WriteLine(text); 23 | return await Task.Run(() => false); 24 | } 25 | 26 | public async Task GroupMessage(GroupMessageReceiver e) { 27 | string q = e.Sender.Group.Id; 28 | Console.ForegroundColor = ConsoleColor.Green; 29 | Console.WriteLine($"{DateTime.Now}\nGroupMessage\t{e.Sender.Group.Name}({e.Sender.Group.Id})"); 30 | Console.ResetColor(); 31 | Console.WriteLine($"User:\t\t{e.Sender.Name}[{e.Sender.Id}]\nContent:\t{Utils.GetMessageText(e.MessageChain)}"); 32 | string text = Utils.GetMessageText(e.MessageChain).Trim(); 33 | Console.WriteLine(text); 34 | return await Task.Run(() => false); 35 | } 36 | 37 | public async Task TempMessage(TempMessageReceiver e) { 38 | string q = e.Sender.Group.Id; 39 | Console.ForegroundColor = ConsoleColor.Green; 40 | Console.WriteLine($"TempMessage\t{e.Sender.Group.Name}({e.Sender.Group.Name})"); 41 | Console.ResetColor(); 42 | Console.WriteLine($"User:\t\t{e.Sender.Name}[{e.Sender.Id}]\nContent:\t{Utils.GetMessageText(e.MessageChain)}"); 43 | string text = Utils.GetMessageText(e.MessageChain).Trim(); 44 | Console.WriteLine(text); 45 | return await Task.Run(() => false); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/Mute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using LQ1Bot.Interface; 4 | using Microsoft.Data.Sqlite; 5 | using Mirai.Net.Data.Messages.Receivers; 6 | using Mirai.Net.Sessions.Http.Managers; 7 | 8 | namespace LQ1Bot.Plugins { 9 | 10 | internal class Mute : PluginBase, IGroupMessage { 11 | public override int Priority => 9993; 12 | 13 | public override string PluginName => "Mute"; 14 | 15 | public override bool CanDisable => true; 16 | 17 | public async Task GroupMessage(GroupMessageReceiver e) { 18 | string text = Utils.GetMessageText(e.MessageChain).ToLower().Trim(); 19 | string q = e.Sender.Group.Id; 20 | #region 禁言抽奖 21 | if (text == "禁言抽奖" || text == "加班抽奖") { 22 | if (e.Sender.Permission != Mirai.Net.Data.Shared.Permissions.Member) { 23 | await MessageManager.SendGroupMessageAsync(q, $"恭喜{e.Sender.Name}抽中了1145141919810分钟禁言套餐!"); 24 | return true; 25 | } 26 | int[] times = { 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 23, 25, 30, 40, 45, 50, 60, 70, 80, 100, 114, 120, 180 }; 27 | int time = times[(new Random()).Next(0, times.Length)]; 28 | await MessageManager.SendGroupMessageAsync(q, $"恭喜{e.Sender.Name}抽中了{time}分钟禁言套餐!"); 29 | await GroupManager.MuteAsync(e.Sender.Id, q, TimeSpan.FromMinutes(time)); 30 | try { 31 | SqliteConnection conn = new SqliteConnection("Data Source=chat.db"); 32 | conn.Open(); 33 | SqliteCommand cmd = new SqliteCommand("", conn) { 34 | CommandText = $"insert into main values (strftime('%Y-%m-%d %H:%M:%f','now','localtime'),@nickname,{e.Sender.Id},{q},'creep')" 35 | }; 36 | cmd.Parameters.AddWithValue("@nickname", e.Sender.Name); 37 | 38 | SqliteDataReader dr = cmd.ExecuteReader(); 39 | dr.Close(); 40 | Console.ForegroundColor = ConsoleColor.DarkGreen; 41 | conn.Close(); 42 | 43 | Console.ResetColor(); 44 | } catch (Exception ee) { 45 | Console.ForegroundColor = ConsoleColor.Red; 46 | Console.WriteLine("写入数据库出现错误\n" + ee.Message); 47 | Console.ResetColor(); 48 | } 49 | return true; 50 | } 51 | #endregion 52 | #region 自助禁言 53 | if (text.StartsWith("自助禁言 ") || text.StartsWith("自助加班 ")) { 54 | if (e.Sender.Permission != Mirai.Net.Data.Shared.Permissions.Member) { 55 | await MessageManager.SendGroupMessageAsync(q, "在?有种把管理卸了"); 56 | return false; 57 | } 58 | if (int.TryParse(text[5..], out int stime)) { 59 | if (stime <= 0) { 60 | await MessageManager.SendGroupMessageAsync(q, $"在?教我怎么设置{stime}分钟禁言"); 61 | } else { 62 | stime = stime > 720 ? 720 : stime; 63 | 64 | await MessageManager.SendGroupMessageAsync(q, $"恭喜{e.Sender.Name}成功领取了{stime}分钟的禁言套餐!"); 65 | await GroupManager.MuteAsync(e.Sender.Id, q, TimeSpan.FromMinutes(stime)); 66 | 67 | try { 68 | SqliteConnection conn = new SqliteConnection("Data Source=chat.db"); 69 | conn.Open(); 70 | SqliteCommand cmd = new SqliteCommand("", conn) { 71 | CommandText = $"insert into main values (strftime('%Y-%m-%d %H:%M:%f','now','localtime'),@nickname,{e.Sender.Id},{q},'creep')" 72 | }; 73 | cmd.Parameters.AddWithValue("@nickname", e.Sender.Name); 74 | 75 | SqliteDataReader dr = cmd.ExecuteReader(); 76 | dr.Close(); 77 | Console.ForegroundColor = ConsoleColor.DarkGreen; 78 | conn.Close(); 79 | 80 | Console.ResetColor(); 81 | } catch (Exception ee) { 82 | Console.ForegroundColor = ConsoleColor.Red; 83 | Console.WriteLine("写入数据库出现错误\n" + ee.Message); 84 | Console.ResetColor(); 85 | } 86 | } 87 | } else { 88 | await MessageManager.SendGroupMessageAsync(q, "在?你管这叫int32整数?"); 89 | } 90 | return true; 91 | } 92 | #endregion 93 | return false; 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/OsuQuery.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | using System.Threading; 4 | using System.Threading.Tasks; 5 | using LQ1Bot.Interface; 6 | using Mirai.Net.Data.Messages.Receivers; 7 | using Mirai.Net.Sessions.Http.Managers; 8 | using Newtonsoft.Json.Linq; 9 | 10 | namespace LQ1Bot.Plugins { 11 | 12 | internal class OsuQuery : PluginBase, IFriendMessage, IGroupMessage { 13 | public override int Priority => 9996; 14 | 15 | public override string PluginName => "OsuQuery"; 16 | public override bool CanDisable => true; 17 | 18 | public async Task FriendMessage(FriendMessageReceiver e) { 19 | string text = Utils.GetMessageText(e.MessageChain); 20 | string q = e.Sender.Id; 21 | #region OSU 22 | if (Regex.IsMatch(text.ToLower(), @"^where .+ (osu|std|mania|ctb|taiko)$|^where .+ ?$")) { 23 | OsuAPI.mode = OsuAPI.OSU; 24 | string s = text.ToLower(); 25 | if (s.IndexOf(' ') != s.LastIndexOf(' ')) { 26 | switch (s[(s.LastIndexOf(' ') + 1)..]) { 27 | case "osu": 28 | case "std": 29 | OsuAPI.mode = OsuAPI.OSU; 30 | s = s[..s.LastIndexOf(' ')]; 31 | break; 32 | 33 | case "ctb": 34 | OsuAPI.mode = OsuAPI.CTB; 35 | s = s[..s.LastIndexOf(' ')]; 36 | break; 37 | 38 | case "mania": 39 | OsuAPI.mode = OsuAPI.MANIA; 40 | s = s[..s.LastIndexOf(' ')]; 41 | break; 42 | 43 | case "taiko": 44 | OsuAPI.mode = OsuAPI.TAIKO; 45 | s = s[..s.LastIndexOf(' ')]; 46 | break; 47 | } 48 | } 49 | Thread t = new Thread(new ThreadStart(() => { 50 | try { 51 | string name = s[(s.IndexOf(' ') + 1)..]; 52 | if (name.IndexOf("'") == -1) { 53 | OsuAPI.PInfo p = OsuAPI.Query(name); 54 | string responce = OsuAPI.GetUserInfo(name, OsuAPI.ReadToken()); 55 | if (responce == "auth") { 56 | Console.ForegroundColor = ConsoleColor.DarkYellow; 57 | Console.WriteLine("Auth needed"); 58 | Console.ResetColor(); 59 | OsuAPI.UpdateToken(); 60 | Thread.Sleep(500); 61 | responce = OsuAPI.GetUserInfo(name, OsuAPI.ReadToken()); 62 | } 63 | switch (responce) { 64 | case "404": 65 | Console.ForegroundColor = ConsoleColor.Yellow; 66 | Console.WriteLine("404 not found"); 67 | Console.ResetColor(); 68 | MessageManager.SendFriendMessageAsync(q, "未找到该玩家!"); 69 | break; 70 | 71 | default: 72 | var jo = JObject.Parse(responce); 73 | JObject stat = (JObject) jo.GetValue("statistics"); 74 | float.TryParse(stat.GetValue("pp")?.ToString(), out float pp2); 75 | int pp = (int) Math.Round(pp2); 76 | int.TryParse(stat.GetValue("global_rank")?.ToString(), out int rank); 77 | string hit_accuracy = stat.GetValue("hit_accuracy")?.ToString() + "%"; 78 | int.TryParse(stat.GetValue("play_count")?.ToString(), out int play_count); 79 | string total_score = stat.GetValue("total_score")?.ToString(); 80 | string total_hits = stat.GetValue("total_hits")?.ToString(); 81 | string maximum_combo = stat.GetValue("maximum_combo")?.ToString(); 82 | JObject rankk = (JObject) stat.GetValue("rank"); 83 | int.TryParse(rankk.GetValue("country")?.ToString(), out int crank); 84 | 85 | OsuAPI.Update(name, pp, rank, crank, play_count); 86 | 87 | int pp1 = p.pp; 88 | int rank1 = p.rank; 89 | int crank1 = p.crank; 90 | int playcount1 = p.playcount; 91 | string info = "玩家" + name + "的osu!个人信息\r\rPP:\t\t" + pp + " (" + (pp - pp1 >= 0 ? "+" : "") + (pp - p.pp) + ")\r全球排名:\t" 92 | + rank + " (" + (rank1 - rank >= 0 ? "+" : "") + (rank1 - rank) + ")\r全国排名:\t" 93 | + crank + " (" + (crank1 - crank >= 0 ? "+" : "") + (crank1 - crank) + ")\r准度:\t\t" 94 | + hit_accuracy + "\r游戏次数:\t" 95 | + play_count + " (" + (play_count - playcount1 >= 0 ? "+" : "") + (play_count - playcount1) + ")\r总分:\t\t" 96 | + total_score + "\r总命中次数:\t" 97 | + total_hits + "\r最大连击数:\t" 98 | + maximum_combo; 99 | MessageManager.SendFriendMessageAsync(q, info); 100 | Console.WriteLine("Query Ended"); 101 | break; 102 | } 103 | } else { 104 | Console.ForegroundColor = ConsoleColor.Yellow; 105 | Console.WriteLine("Sql Inject Detected"); 106 | Console.ResetColor(); 107 | try { 108 | OsuAPI.PInfo p = OsuAPI.QueryInjectable(ref name); 109 | string info = "玩家" + name + "的osu!个人信息\r\rPP:\t\t" + p.pp + "\r全球排名:\t" 110 | + p.rank + "\r全国排名:\t" 111 | + p.crank + "\r准度:\t\t" 112 | + "0.0%" + "\r游戏次数:\t" 113 | + p.playcount + "\r总分:\t\t" 114 | + "0" + "\r总命中次数:\t" 115 | + "0" + "\r最大连击数:\t" 116 | + "0"; 117 | MessageManager.SendFriendMessageAsync(q, info); 118 | Console.WriteLine("Query Ended"); 119 | } catch (Exception e) { 120 | Console.WriteLine(e.Message); 121 | MessageManager.SendFriendMessageAsync(q, e.Message); 122 | } 123 | } 124 | } catch (Exception e) { 125 | Console.ForegroundColor = ConsoleColor.Red; 126 | Console.WriteLine("Osu Query failed"); 127 | Console.WriteLine(e); 128 | Console.ResetColor(); 129 | } 130 | })); 131 | t.Start(); 132 | return true; 133 | } 134 | #endregion 135 | return await Task.Run(() => false); 136 | } 137 | 138 | public async Task GroupMessage(GroupMessageReceiver e) { 139 | string text = Utils.GetMessageText(e.MessageChain); 140 | string q = e.Sender.Group.Id; 141 | #region OSU 142 | if (Regex.IsMatch(text.ToLower(), @"^where .+ (osu|std|mania|ctb|taiko)$|^where .+ ?$")) { 143 | OsuAPI.mode = OsuAPI.OSU; 144 | string s = text.ToLower(); 145 | if (s.IndexOf(' ') != s.LastIndexOf(' ')) { 146 | switch (s[(s.LastIndexOf(' ') + 1)..]) { 147 | case "osu": 148 | case "std": 149 | OsuAPI.mode = OsuAPI.OSU; 150 | s = s[..s.LastIndexOf(' ')]; 151 | break; 152 | 153 | case "ctb": 154 | OsuAPI.mode = OsuAPI.CTB; 155 | s = s[..s.LastIndexOf(' ')]; 156 | break; 157 | 158 | case "mania": 159 | OsuAPI.mode = OsuAPI.MANIA; 160 | s = s[..s.LastIndexOf(' ')]; 161 | break; 162 | 163 | case "taiko": 164 | OsuAPI.mode = OsuAPI.TAIKO; 165 | s = s[..s.LastIndexOf(' ')]; 166 | break; 167 | } 168 | } 169 | try { 170 | string name = s[(s.IndexOf(' ') + 1)..]; 171 | if (name.IndexOf("'") == -1) { 172 | OsuAPI.PInfo p = OsuAPI.Query(name); 173 | string responce = OsuAPI.GetUserInfo(name, OsuAPI.ReadToken()); 174 | if (responce == "auth") { 175 | Console.ForegroundColor = ConsoleColor.DarkYellow; 176 | Console.WriteLine("Auth needed"); 177 | Console.ResetColor(); 178 | OsuAPI.UpdateToken(); 179 | Thread.Sleep(500); 180 | responce = OsuAPI.GetUserInfo(name, OsuAPI.ReadToken()); 181 | } 182 | switch (responce) { 183 | case "404": 184 | Console.ForegroundColor = ConsoleColor.Yellow; 185 | Console.WriteLine("404 not found"); 186 | Console.ResetColor(); 187 | await MessageManager.SendGroupMessageAsync(q, "未找到该玩家!"); 188 | break; 189 | 190 | default: 191 | var jo = JObject.Parse(responce); 192 | JObject stat = (JObject) jo.GetValue("statistics"); 193 | float.TryParse(stat.GetValue("pp")?.ToString(), out float pp2); 194 | int pp = (int) Math.Round(pp2); 195 | int.TryParse(stat.GetValue("global_rank")?.ToString(), out int rank); 196 | string hit_accuracy = stat.GetValue("hit_accuracy")?.ToString() + "%"; 197 | int.TryParse(stat.GetValue("play_count")?.ToString(), out int play_count); 198 | string total_score = stat.GetValue("total_score")?.ToString(); 199 | string total_hits = stat.GetValue("total_hits")?.ToString(); 200 | string maximum_combo = stat.GetValue("maximum_combo")?.ToString(); 201 | JObject rankk = (JObject) stat.GetValue("rank"); 202 | int.TryParse(rankk.GetValue("country")?.ToString(), out int crank); 203 | 204 | OsuAPI.Update(name, pp, rank, crank, play_count); 205 | 206 | int pp1 = p.pp; 207 | int rank1 = p.rank; 208 | int crank1 = p.crank; 209 | int playcount1 = p.playcount; 210 | string info = "玩家" + name + "的osu!个人信息\r\rPP:\t\t" + pp + " (" + (pp - pp1 >= 0 ? "+" : "") + (pp - p.pp) + ")\r全球排名:\t" 211 | + rank + " (" + (rank1 - rank >= 0 ? "+" : "") + (rank1 - rank) + ")\r全国排名:\t" 212 | + crank + " (" + (crank1 - crank >= 0 ? "+" : "") + (crank1 - crank) + ")\r准度:\t\t" 213 | + hit_accuracy + "\r游戏次数:\t" 214 | + play_count + " (" + (play_count - playcount1 >= 0 ? "+" : "") + (play_count - playcount1) + ")\r总分:\t\t" 215 | + total_score + "\r总命中次数:\t" 216 | + total_hits + "\r最大连击数:\t" 217 | + maximum_combo; 218 | await MessageManager.SendGroupMessageAsync(q, info); 219 | Console.WriteLine("Query Ended"); 220 | break; 221 | } 222 | } else { 223 | Console.ForegroundColor = ConsoleColor.Yellow; 224 | Console.WriteLine("Sql Inject Detected"); 225 | Console.ResetColor(); 226 | try { 227 | OsuAPI.PInfo p = OsuAPI.QueryInjectable(ref name); 228 | string info = "玩家" + name + "的osu!个人信息\r\rPP:\t\t" + p.pp + "\r全球排名:\t" 229 | + p.rank + "\r全国排名:\t" 230 | + p.crank + "\r准度:\t\t" 231 | + "0.0%" + "\r游戏次数:\t" 232 | + p.playcount + "\r总分:\t\t" 233 | + "0" + "\r总命中次数:\t" 234 | + "0" + "\r最大连击数:\t" 235 | + "0"; 236 | await MessageManager.SendGroupMessageAsync(q, info); 237 | Console.WriteLine("Query Ended"); 238 | } catch (Exception ee) { 239 | Console.WriteLine(ee.Message); 240 | await MessageManager.SendGroupMessageAsync(q, ee.Message); 241 | } 242 | } 243 | } catch (Exception ee) { 244 | Console.ForegroundColor = ConsoleColor.Red; 245 | Console.WriteLine("Osu Query failed"); 246 | Console.WriteLine(ee); 247 | Console.ResetColor(); 248 | } 249 | return true; 250 | } 251 | #endregion 252 | return false; 253 | } 254 | } 255 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/PermissionMgr.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Threading.Tasks; 5 | using LQ1Bot.Interface; 6 | using Mirai.Net.Data.Messages.Receivers; 7 | using Mirai.Net.Sessions.Http.Managers; 8 | using Newtonsoft.Json.Linq; 9 | 10 | namespace LQ1Bot.Plugins { 11 | 12 | internal class PermissionMgr : PluginBase, IGroupMessage, IFriendMessage { 13 | public override int Priority => 50000; 14 | 15 | public override string PluginName => "PermissionMgr"; 16 | 17 | public override bool CanDisable => false; 18 | 19 | private static readonly Dictionary> Permissions = new Dictionary>(); 20 | public PermissionMgr() { 21 | if (File.Exists("permissions.json")) { 22 | try { 23 | string json = File.ReadAllText("permissions.json"); 24 | JObject o = JObject.Parse(json); 25 | foreach (var v in o) { 26 | Permissions.Add(v.Key, v.Value.ToObject>()); 27 | } 28 | Console.WriteLine(JObject.FromObject(Permissions).ToString()); 29 | } catch (Exception e) { 30 | Console.WriteLine(e.Message); 31 | } 32 | } 33 | } 34 | 35 | public async Task GroupMessage(GroupMessageReceiver e) { 36 | string text = Utils.GetMessageText(e.MessageChain); 37 | string q = e.Sender.Group.Id; 38 | if (text == "whoami") { 39 | await MessageManager.SendGroupMessageAsync(q, "permissions: " + string.Join(",", Permissions.GetValueOrDefault(e.Sender.Id))); 40 | } 41 | if (Permissions.GetValueOrDefault(e.Sender.Id)?.Contains("admin") ?? false) { 42 | if (text.StartsWith("!ban ")) { 43 | string id = text[5..]; 44 | if (long.TryParse(id, out long id2ban)) { 45 | if (Permissions.TryGetValue(id2ban.ToString(), out HashSet permissions)) { 46 | permissions.Add("banned"); 47 | } else { 48 | Permissions.Add(id2ban.ToString(), new HashSet() { "banned" }); 49 | } 50 | Save(); 51 | await MessageManager.SendGroupMessageAsync(q, "已屏蔽" + id2ban); 52 | } else { 53 | await MessageManager.SendGroupMessageAsync(q, "输入格式错误"); 54 | } 55 | } 56 | if (text.StartsWith("!unban ")) { 57 | string id = text[7..]; 58 | if (long.TryParse(id, out long id2ban)) { 59 | Permissions.Remove(id2ban.ToString()); 60 | Save(); 61 | await MessageManager.SendGroupMessageAsync(q, "已解封" + id2ban); 62 | } else { 63 | await MessageManager.SendGroupMessageAsync(q, "输入格式错误"); 64 | } 65 | } 66 | return false; 67 | } 68 | return Permissions.GetValueOrDefault(e.Sender.Id)?.Contains("banned") ?? false; 69 | } 70 | 71 | public async Task FriendMessage(FriendMessageReceiver e) { 72 | string text = Utils.GetMessageText(e.MessageChain); 73 | string q = e.Sender.Id; 74 | if (text == "whoami") { 75 | await MessageManager.SendFriendMessageAsync(q, "permissions: " + string.Join(",", Permissions.GetValueOrDefault(e.Sender.Id))); 76 | } 77 | if (Permissions.GetValueOrDefault(e.Sender.Id)?.Contains("admin") ?? false) { 78 | if (text.StartsWith("!ban ")) { 79 | string id = text[5..]; 80 | if (long.TryParse(id, out long id2ban)) { 81 | if (Permissions.TryGetValue(id2ban.ToString(), out HashSet permissions)) { 82 | permissions.Add("banned"); 83 | } else { 84 | Permissions.Add(id2ban.ToString(), new HashSet() { "banned" }); 85 | } 86 | Save(); 87 | await MessageManager.SendFriendMessageAsync(q, "已屏蔽" + id2ban); 88 | } else { 89 | await MessageManager.SendFriendMessageAsync(q, "输入格式错误"); 90 | } 91 | } 92 | if (text.StartsWith("!unban ")) { 93 | string id = text[7..]; 94 | if (long.TryParse(id, out long id2ban)) { 95 | Permissions.Remove(id2ban.ToString()); 96 | Save(); 97 | await MessageManager.SendFriendMessageAsync(q, "已解封" + id2ban); 98 | } else { 99 | await MessageManager.SendFriendMessageAsync(q, "输入格式错误"); 100 | } 101 | } 102 | return false; 103 | } 104 | return false; 105 | //return Permissions.GetValueOrDefault(e.Sender.Id)?.Contains("banned") ?? false; 106 | } 107 | 108 | 109 | private void Save() { 110 | File.WriteAllText("permissions.json", JObject.FromObject(Permissions).ToString()); 111 | } 112 | public static bool HasPermissionOrAdmin(string id, string permission) { 113 | return HasPermission(id, permission) || IsBotAdmin(id); 114 | } 115 | public static bool HasPermission(string id, string permission) { 116 | if (Permissions.TryGetValue(id, out HashSet permissions)) { 117 | return permissions.Contains(permission); 118 | } 119 | return false; 120 | } 121 | public static HashSet GetPermissions(string id) { 122 | if (Permissions.TryGetValue(id, out HashSet permissions)) { 123 | return permissions; 124 | } else { 125 | var permission = new HashSet(); 126 | Permissions.Add(id, permission); 127 | return permission; 128 | } 129 | } 130 | public static bool IsGroupOrBotAdmin(Mirai.Net.Data.Shared.Member q) { 131 | return q.Permission != Mirai.Net.Data.Shared.Permissions.Member || (Permissions.GetValueOrDefault(q.Id)?.Contains("admin") ?? false); 132 | } 133 | public static bool IsBotAdmin(string q) { 134 | return Permissions.GetValueOrDefault(q)?.Contains("admin") ?? false; 135 | } 136 | } 137 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/Picker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text.RegularExpressions; 4 | using System.Threading.Tasks; 5 | using LQ1Bot.Interface; 6 | using Mirai.Net.Data.Messages.Receivers; 7 | using Mirai.Net.Sessions.Http.Managers; 8 | 9 | namespace LQ1Bot.Plugins { 10 | 11 | internal class Picker : PluginBase, IGroupMessage { 12 | public override int Priority => 9991; 13 | 14 | public override bool CanDisable => true; 15 | public override string PluginName => "Picker"; 16 | 17 | private struct Pick { 18 | public string qq; 19 | public string Name; 20 | public int PickCount; 21 | public int Total; 22 | public Dictionary Player; 23 | } 24 | 25 | private readonly List PickRecord = new List(); 26 | 27 | public async Task GroupMessage(GroupMessageReceiver e) { 28 | string text = Utils.GetMessageText(e.MessageChain).ToLower(); 29 | string q = e.Sender.Group.Id; 30 | #region 抽奖 31 | if (Regex.IsMatch(text.ToLower(), @"^[!!]pick start \d{1,3}/\d{1,10} \S+$")) { 32 | int PickCount = int.Parse(text.ToLower().Split(' ')[2].Split('/')[0]); 33 | int Total = int.Parse(text.ToLower().Split(' ')[2].Split('/')[1]); 34 | string name = text.ToLower().Split(' ')[3]; 35 | if (PickCount < 1) { 36 | await MessageManager.SendGroupMessageAsync(q, $"能教我一下怎么抽{PickCount}个人吗?"); 37 | return true; 38 | } 39 | if (PickCount > Total) { 40 | await MessageManager.SendGroupMessageAsync(q, $"能教我一下怎么从{Total}个人中抽出{PickCount}个人吗?"); 41 | return true; 42 | } 43 | 44 | foreach (var v in PickRecord) { 45 | if (v.Name == name) { 46 | await MessageManager.SendGroupMessageAsync(q, $"已存在名称为{name}的抽奖!"); 47 | return true; 48 | } 49 | } 50 | 51 | PickRecord.Add(new Pick() { 52 | Name = name, 53 | qq = e.Sender.Id, 54 | PickCount = PickCount, 55 | Total = Total, 56 | Player = new Dictionary() 57 | }); 58 | await MessageManager.SendGroupMessageAsync(q, $"已添加名称为{name}的抽奖!\n将从最多{Total}人中抽取{PickCount}人\n输入!pick join {name}即可参与抽奖"); 59 | return true; 60 | } 61 | if (Regex.IsMatch(text.ToLower(), @"^[!!]pick join \S+$")) { 62 | string name = text.ToLower().Split(' ')[2]; 63 | foreach (var v in PickRecord) { 64 | if (v.Name == name) { 65 | if (v.Player.Count < v.Total) { 66 | if (v.Player.ContainsKey(e.Sender.Id)) { 67 | await MessageManager.SendGroupMessageAsync(q, "您已参与该抽奖!"); 68 | } else { 69 | v.Player.Add(e.Sender.Id, e.Sender.Name); 70 | await MessageManager.SendGroupMessageAsync(q,$"成功参与抽奖!当前参与人数:{v.Player.Count}/{v.Total}"); 71 | } 72 | } else { 73 | await MessageManager.SendGroupMessageAsync(q, $"抽奖人数已达{v.Total}人上限!"); 74 | } 75 | return true; 76 | } 77 | } 78 | await MessageManager.SendGroupMessageAsync(q, "未找到该抽奖!"); 79 | return true; 80 | } 81 | if (Regex.IsMatch(text.ToLower(), @"^[!!]pick end \S+$")) { 82 | string name = text.ToLower().Split(' ')[2]; 83 | foreach (var v in PickRecord) { 84 | if (v.Name == name) { 85 | if (v.qq != e.Sender.Id && e.Sender.Permission == Mirai.Net.Data.Shared.Permissions.Member) { 86 | await MessageManager.SendGroupMessageAsync(q, "您不是该抽奖的发起者!"); 87 | } else { 88 | if (v.Player.Count < v.PickCount) { 89 | await MessageManager.SendGroupMessageAsync(q, $"参与抽奖的人数未达到抽奖所需的最小人数!\n当前参与抽奖的人数为:{ v.Player.Count}/{ v.Total},至少要有{ v.PickCount}人参与才能抽奖!"); 90 | } else { 91 | var l = new List(); 92 | foreach (var vv in v.Player) { 93 | l.Add(vv.Key); 94 | } 95 | var ll = new List(); 96 | for (int i = 0; i < v.PickCount; i++) { 97 | int rnd = (new Random()).Next(0, l.Count); 98 | ll.Add(l[rnd]); 99 | l.RemoveAt(rnd); 100 | } 101 | var lllll = new List(); 102 | foreach (var vv in ll) { 103 | v.Player.TryGetValue(vv, out string temp); 104 | lllll.Add(temp); 105 | } 106 | string resultt = string.Join(",", lllll.ToArray()); 107 | await MessageManager.SendGroupMessageAsync(q, $"恭喜{resultt}中奖!"); 108 | PickRecord.Remove(v); 109 | } 110 | } 111 | return true; 112 | } 113 | } 114 | await MessageManager.SendGroupMessageAsync(q, "未找到该抽奖!"); 115 | return true; 116 | } 117 | if (Regex.IsMatch(text.ToLower(), @"^[!!]pick remove \S+$")) { 118 | string name = text.ToLower().Split(' ')[2]; 119 | foreach (var v in PickRecord) { 120 | if (v.Name == name) { 121 | if (e.Sender.Id != v.qq && e.Sender.Permission == Mirai.Net.Data.Shared.Permissions.Member) { 122 | await MessageManager.SendGroupMessageAsync(q, "你不是该抽奖的发起者!"); 123 | return true; 124 | } else { 125 | PickRecord.Remove(v); 126 | await MessageManager.SendGroupMessageAsync(q, $"已移除{name}"); 127 | return true; 128 | } 129 | } 130 | } 131 | await MessageManager.SendGroupMessageAsync(q, "未找到该抽奖!"); 132 | return true; 133 | } 134 | if (Regex.IsMatch(text.ToLower(), @"^[!!]pick info$")) { 135 | if (PickRecord.Count == 0) { 136 | await MessageManager.SendGroupMessageAsync(q, "当前还没有抽奖!"); 137 | } else { 138 | string resultt = "当前所有抽奖"; 139 | foreach (var v in PickRecord) { 140 | resultt += $"\n{v.Name},从最多{v.Total}人中抽取{v.PickCount}人,目前已有{v.Player.Count}人参与"; 141 | } 142 | await MessageManager.SendGroupMessageAsync(q, resultt); 143 | } 144 | return true; 145 | } 146 | #endregion 147 | return false; 148 | } 149 | } 150 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/RndPwdGen.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | using System.Threading.Tasks; 3 | using LQ1Bot.Interface; 4 | using Mirai.Net.Data.Messages.Receivers; 5 | using Mirai.Net.Sessions.Http.Managers; 6 | 7 | namespace LQ1Bot.Plugins { 8 | 9 | internal class RndPwdGen : PluginBase, IGroupMessage, IFriendMessage { 10 | public override int Priority => 9990; 11 | 12 | public override bool CanDisable => true; 13 | public override string PluginName => "RandomPasswordGenerator"; 14 | 15 | public async Task FriendMessage(FriendMessageReceiver e) { 16 | string text = Utils.GetMessageText(e.MessageChain).ToLower(); 17 | #region 强随机密码生成器 18 | if (Regex.IsMatch(text, @"^[!!]pwd(? \d+)?(? \S+)?$")) { 19 | var m = Regex.Match(text, @"^[!!]pwd(? \d+)?(? \S+)?$"); 20 | string len = m.Groups["len"].Value; 21 | if (!int.TryParse(len, out int Length) || Length < 1 || Length > 64) { 22 | Length = 16; 23 | } 24 | string pattern = m.Groups["pat"].Value; 25 | pattern = pattern.Length < 1 ? "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" : pattern[1..]; 26 | await MessageManager.SendFriendMessageAsync(e.Sender.Id, Utils.GetStrongRandomString(Length, pattern)); 27 | return true; 28 | } 29 | #endregion 30 | return false; 31 | } 32 | 33 | public async Task GroupMessage(GroupMessageReceiver e) { 34 | string text = Utils.GetMessageText(e.MessageChain).ToLower(); 35 | #region 强随机密码生成器 36 | if (Regex.IsMatch(text, @"^[!!]pwd(? \d+)?(? \S+)?$")) { 37 | var m = Regex.Match(text, @"^[!!]pwd(? \d+)?(? \S+)?$"); 38 | string len = m.Groups["len"].Value; 39 | if (!int.TryParse(len, out int Length) || Length < 1 || Length > 64) { 40 | Length = 16; 41 | } 42 | string pattern = m.Groups["pat"].Value; 43 | pattern = pattern.Length < 1 ? "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" : pattern[1..]; 44 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, Utils.GetStrongRandomString(Length, pattern)); 45 | return true; 46 | } 47 | #endregion 48 | return false; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/SwitchControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text.Json; 5 | using System.Threading.Tasks; 6 | using LQ1Bot.Interface; 7 | using Mirai.Net.Data.Messages.Receivers; 8 | using Mirai.Net.Sessions.Http.Managers; 9 | 10 | namespace LQ1Bot.Plugins { 11 | 12 | internal class SwitchControl : PluginBase, IGroupMessage { 13 | public override int Priority => 20000; 14 | 15 | public override string PluginName => "SwitchControl"; 16 | public override bool CanDisable => false; 17 | 18 | private static HashSet BlacklistGroups; 19 | 20 | public SwitchControl() { 21 | if (File.Exists("blacklist.json")) { 22 | try { 23 | BlacklistGroups = JsonSerializer.Deserialize>(File.ReadAllText("blacklist.json")); 24 | } catch (Exception) { } 25 | } 26 | if (BlacklistGroups != null) { 27 | if (BlacklistGroups.Count > 0) { 28 | Console.ForegroundColor = ConsoleColor.DarkYellow; 29 | Console.WriteLine("[黑名单群]"); 30 | foreach (var v in BlacklistGroups) { 31 | Console.WriteLine(v); 32 | } 33 | Console.ResetColor(); 34 | } 35 | } 36 | } 37 | 38 | public async Task GroupMessage(GroupMessageReceiver e) { 39 | string text = Utils.GetMessageText(e.MessageChain).ToLower(); 40 | string q = e.Sender.Group.Id; 41 | #region 启用/禁用控制 42 | if (text == "!enablebot") { 43 | if (PermissionMgr.IsGroupOrBotAdmin(e.Sender)) { 44 | if (BlacklistGroups == null) { 45 | BlacklistGroups = new HashSet(); 46 | } else { 47 | BlacklistGroups.Remove(long.Parse(q)); 48 | } 49 | await MessageManager.SendGroupMessageAsync(q, "已在此群启用bot"); 50 | File.WriteAllText("blacklist.json", JsonSerializer.Serialize(BlacklistGroups)); 51 | return true; 52 | } 53 | } 54 | 55 | if (BlacklistGroups?.Contains(long.Parse(q)) ?? false) { 56 | return true; 57 | } 58 | 59 | if (text == "!banbot" || text == "!disablebot") { 60 | if (PermissionMgr.IsGroupOrBotAdmin(e.Sender)) { 61 | if (BlacklistGroups == null) { 62 | BlacklistGroups = new HashSet() { long.Parse(q) }; 63 | } else { 64 | BlacklistGroups.Add(long.Parse(q)); 65 | } 66 | await MessageManager.SendGroupMessageAsync(q, "已在此群禁用bot"); 67 | File.WriteAllText("blacklist.json", JsonSerializer.Serialize(BlacklistGroups)); 68 | return true; 69 | } 70 | } 71 | #endregion 72 | return false; 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/Translater.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | using System.Security.Cryptography; 5 | using System.Text.RegularExpressions; 6 | using System.Threading.Tasks; 7 | using System.Web; 8 | using LQ1Bot.Interface; 9 | using Mirai.Net.Data.Messages.Receivers; 10 | using Mirai.Net.Sessions.Http.Managers; 11 | using Newtonsoft.Json.Linq; 12 | 13 | namespace LQ1Bot.Plugins { 14 | 15 | internal class Translater : PluginBase, IGroupMessage, IFriendMessage { 16 | public override int Priority => 9989; 17 | public override bool CanDisable => true; 18 | 19 | public override string PluginName => "Translater"; 20 | 21 | public async Task FriendMessage(FriendMessageReceiver e) { 22 | string text = Utils.GetMessageText(e.MessageChain); 23 | #region 机翻 24 | if (Regex.IsMatch(text, @"^翻译([a-z]{1,3})? .+$")) { 25 | string ToTranslate = text[(text.IndexOf(' ') + 1)..]; 26 | string Lang = text[2] == ' ' ? "zh" : text.Split(' ')[0][2..]; 27 | if (Lang == "cn") 28 | Lang = "zh"; 29 | string AppId = Program.Secret.BaiduTranslateAppId; 30 | string salt = RandomNumberGenerator.GetInt32(1000000, 9999999).ToString(); 31 | Console.WriteLine(salt); 32 | string sign = Utils.GetMD5(AppId + ToTranslate + salt + Program.Secret.BaiduTranslateSecret); 33 | Console.WriteLine(sign); 34 | string url = @"http://" + @$"api.fanyi.baidu.com/api/trans/vip/translate?q={HttpUtility.UrlEncode(ToTranslate)}&from=auto&to={Lang}&appid={AppId}&salt={salt}&sign={sign}"; 35 | HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url); 36 | req.Timeout = 5000; 37 | string result = ""; 38 | try { 39 | HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); 40 | Stream stream = resp.GetResponseStream(); 41 | using (StreamReader reader = new StreamReader(stream)) { 42 | result = reader.ReadToEnd(); 43 | } 44 | stream.Close(); 45 | Console.WriteLine(result); 46 | JObject o = JObject.Parse(result); 47 | 48 | if (o.ContainsKey("error_code") && o["error_code"].ToString() == "58001") { 49 | await MessageManager.SendFriendMessageAsync(e.Sender.Id, "翻译语言选择错误"); 50 | return true; 51 | } 52 | 53 | string TranslationResult = o["trans_result"][0]["dst"].ToString(); 54 | await MessageManager.SendFriendMessageAsync(e.Sender.Id, $"翻译结果:{TranslationResult}"); 55 | } catch (Exception eee) { 56 | Console.WriteLine(eee.Message); 57 | await MessageManager.SendFriendMessageAsync(e.Sender.Id, "获取翻译出错"); 58 | } 59 | return true; 60 | } 61 | #endregion 62 | return false; 63 | } 64 | 65 | public async Task GroupMessage(GroupMessageReceiver e) { 66 | string text = Utils.GetMessageText(e.MessageChain); 67 | #region 机翻 68 | if (Regex.IsMatch(text, @"^翻译([a-z]{1,3})? .+$")) { 69 | string ToTranslate = text[(text.IndexOf(' ') + 1)..]; 70 | string Lang = text[2] == ' ' ? "zh" : text.Split(' ')[0][2..]; 71 | if (Lang == "cn") 72 | Lang = "zh"; 73 | string AppId = Program.Secret.BaiduTranslateAppId; 74 | string salt = RandomNumberGenerator.GetInt32(1000000, 9999999).ToString(); 75 | Console.WriteLine(salt); 76 | string sign = Utils.GetMD5(AppId + ToTranslate + salt + Program.Secret.BaiduTranslateSecret); 77 | Console.WriteLine(sign); 78 | string url = @"http://" + @$"api.fanyi.baidu.com/api/trans/vip/translate?q={HttpUtility.UrlEncode(ToTranslate)}&from=auto&to={Lang}&appid={AppId}&salt={salt}&sign={sign}"; 79 | HttpWebRequest req = (HttpWebRequest) WebRequest.Create(url); 80 | req.Timeout = 5000; 81 | string result = ""; 82 | try { 83 | HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); 84 | Stream stream = resp.GetResponseStream(); 85 | using (StreamReader reader = new StreamReader(stream)) { 86 | result = reader.ReadToEnd(); 87 | } 88 | stream.Close(); 89 | Console.WriteLine(result); 90 | JObject o = JObject.Parse(result); 91 | 92 | if (o.ContainsKey("error_code") && o["error_code"].ToString() == "58001") { 93 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "翻译语言选择错误"); 94 | return true; 95 | } 96 | 97 | string TranslationResult = o["trans_result"][0]["dst"].ToString(); 98 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, $"翻译结果:{TranslationResult}"); 99 | } catch (Exception eee) { 100 | Console.WriteLine(eee.Message); 101 | await MessageManager.SendGroupMessageAsync(e.Sender.Group.Id, "获取翻译出错"); 102 | } 103 | return true; 104 | } 105 | #endregion 106 | return false; 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/Weather.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using LQ1Bot.Interface; 4 | using Mirai.Net.Data.Messages.Receivers; 5 | using Mirai.Net.Sessions.Http.Managers; 6 | using Newtonsoft.Json.Linq; 7 | using Flurl.Http; 8 | using System.Collections.Generic; 9 | 10 | namespace LQ1Bot.Plugins { 11 | 12 | internal class Weather : PluginBase, IGroupMessage, IFriendMessage { 13 | public override int Priority => 9980; 14 | 15 | public override string PluginName => "Weather"; 16 | 17 | public override bool CanDisable => true; 18 | 19 | public async Task FriendMessage(FriendMessageReceiver e) { 20 | string text = Utils.GetMessageText(e.MessageChain); 21 | string q = e.Sender.Id; 22 | if (text.Length < 15 && text.StartsWith("天气查询 ")) { 23 | try { 24 | string city = text[5..]; 25 | string result = await $"https://query.asilu.com/weather/gaode/?city={city}" 26 | .GetStringAsync(); 27 | JObject o = JObject.Parse(result); 28 | if (((JArray) o["forecasts"]).Count > 0) { 29 | JArray casts = (JArray) o["forecasts"][0]["casts"]; 30 | string name = o["forecasts"][0]["city"].ToString(); 31 | string time = o["forecasts"][0]["reporttime"].ToString(); 32 | string dayweather = $"{casts[0]["dayweather"]} {casts[0]["daytemp"]}℃ {casts[0]["daywind"]}风{casts[0]["daypower"]}级"; 33 | string nightweather = $"{casts[0]["nightweather"]} {casts[0]["nighttemp"]}℃ {casts[0]["nightwind"]}风{casts[0]["nightpower"]}级"; 34 | string msg = $"{name}天气 更新时间:{time}\n日间天气:{dayweather}\n夜间天气:{nightweather}"; 35 | 36 | List fc = new(); 37 | for (int i = 1; i < casts.Count; i++) { 38 | dayweather = $"{casts[i]["dayweather"]} {casts[i]["daytemp"]}℃ {casts[i]["daywind"]}风{casts[i]["daypower"]}级"; 39 | nightweather = $"{casts[i]["nightweather"]} {casts[i]["nighttemp"]}℃ {casts[i]["nightwind"]}风{casts[i]["nightpower"]}级"; 40 | fc.Add(casts[i]["date"] + ": " + dayweather + " => " + nightweather); 41 | } 42 | 43 | msg += "\n" + string.Join("\n", fc); 44 | await MessageManager.SendFriendMessageAsync(q, msg); 45 | } else { 46 | await MessageManager.SendFriendMessageAsync(q, "城市名称错误!"); 47 | } 48 | } catch (Exception ex) { 49 | Console.WriteLine(ex); 50 | await MessageManager.SendFriendMessageAsync(q, "获取天气出错"); 51 | } 52 | return true; 53 | } 54 | return false; 55 | } 56 | 57 | public async Task GroupMessage(GroupMessageReceiver e) { 58 | string text = Utils.GetMessageText(e.MessageChain); 59 | string q = e.Sender.Group.Id; 60 | if (text.Length < 15 && text.StartsWith("天气查询 ")) { 61 | try { 62 | string city = text[5..]; 63 | string result = await $"https://query.asilu.com/weather/gaode/?city={city}" 64 | .GetStringAsync(); 65 | JObject o = JObject.Parse(result); 66 | if (((JArray) o["forecasts"]).Count > 0) { 67 | JArray casts = (JArray) o["forecasts"][0]["casts"]; 68 | string name = o["forecasts"][0]["city"].ToString(); 69 | string time = o["forecasts"][0]["reporttime"].ToString(); 70 | string dayweather = $"{casts[0]["dayweather"]} {casts[0]["daytemp"]}℃ {casts[0]["daywind"]}风{casts[0]["daypower"]}级"; 71 | string nightweather = $"{casts[0]["nightweather"]} {casts[0]["nighttemp"]}℃ {casts[0]["nightwind"]}风{casts[0]["nightpower"]}级"; 72 | string msg = $"{name}天气 更新时间:{time}\n日间天气:{dayweather}\n夜间天气:{nightweather}"; 73 | 74 | List fc = new(); 75 | for (int i = 1; i < casts.Count; i++) { 76 | dayweather = $"{casts[i]["dayweather"]} {casts[i]["daytemp"]}℃ {casts[i]["daywind"]}风{casts[i]["daypower"]}级"; 77 | nightweather = $"{casts[i]["nightweather"]} {casts[i]["nighttemp"]}℃ {casts[i]["nightwind"]}风{casts[i]["nightpower"]}级"; 78 | fc.Add(casts[i]["date"] + ": " + dayweather + " => " + nightweather); 79 | } 80 | 81 | msg += "\n" + string.Join("\n", fc); 82 | await MessageManager.SendGroupMessageAsync(q, msg); 83 | } else { 84 | await MessageManager.SendGroupMessageAsync(q, "城市名称错误!"); 85 | } 86 | } catch (Exception ex) { 87 | Console.WriteLine(ex); 88 | await MessageManager.SendGroupMessageAsync(q, "获取天气出错"); 89 | } 90 | return true; 91 | } 92 | return false; 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /LQ1Bot/Plugins/WhatIsThis.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Security.Cryptography; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Threading.Tasks; 9 | using System.Web; 10 | using Flurl.Http; 11 | using LQ1Bot.Interface; 12 | using Mirai.Net.Data.Messages.Receivers; 13 | using Mirai.Net.Sessions.Http.Managers; 14 | using Newtonsoft.Json; 15 | using Newtonsoft.Json.Linq; 16 | 17 | namespace LQ1Bot.Plugins { 18 | 19 | internal class WhatIsThis : PluginBase, IGroupMessage, IFriendMessage { 20 | public override int Priority => 9987; 21 | 22 | public override string PluginName => "WhatIsThis"; 23 | 24 | public override bool CanDisable => true; 25 | 26 | private DateTime Cooldown = DateTime.Now; 27 | 28 | public async Task FriendMessage(FriendMessageReceiver e) { 29 | string text = Utils.GetMessageText(e.MessageChain); 30 | 31 | string q = e.Sender.Id; 32 | 33 | if (Regex.IsMatch(text, @"^.{1,20}是啥。。。$")) { 34 | if (DateTime.Now < Cooldown) { 35 | await MessageManager.SendFriendMessageAsync(q, "功能正在冷却,请稍后再试"); 36 | return true; 37 | } 38 | 39 | text = text[..^5]; 40 | try { 41 | var o = new { 42 | phrase = text, 43 | page = 1 44 | }; 45 | 46 | string json = JsonConvert.SerializeObject(o, Formatting.None); 47 | Console.WriteLine(json); 48 | 49 | string resp = await "https://api.jikipedia.com/go/search_entities" 50 | .WithHeader("Content-Type", "application/json;charset=utf-8") 51 | .WithHeader("Client", "web") 52 | .WithHeader("Client-Version", "2.7.2k") 53 | .WithHeader("XID", GenerateXID()) 54 | .PostJsonAsync(o) 55 | .ReceiveString(); 56 | 57 | 58 | JObject responceJson = JObject.Parse(resp); 59 | 60 | JArray dataArray = (JArray) responceJson["data"]; 61 | 62 | foreach (var dat in dataArray) { 63 | if (dat["category"].ToString() == "definition") { 64 | string name = dat["definitions"][0]["term"]["title"].ToString(); 65 | string def = dat["definitions"][0]["content"].ToString(); 66 | 67 | //中括号去除 68 | def = Regex.Replace(def, @"\[.+(,.+)*:(?.+)\]", "${str}"); 69 | 70 | await MessageManager.SendFriendMessageAsync(q, $"可能的全名:{name}\n释义:{def}\n详细信息:https://jikipedia.com/search?phrase={HttpUtility.UrlEncode(text)}"); 71 | 72 | //添加全局冷却 73 | Cooldown = DateTime.Now.AddMinutes(0.5); 74 | 75 | return true; 76 | } 77 | } 78 | await MessageManager.SendGroupMessageAsync(q, "未找到解释!"); 79 | } catch (WebException eee) { 80 | if (((HttpWebResponse) eee.Response).StatusCode == HttpStatusCode.Locked) { 81 | Cooldown = DateTime.Now.AddMinutes(5.0); 82 | await MessageManager.SendFriendMessageAsync(q, "请求次数过多,请稍后再试"); 83 | return true; 84 | } 85 | 86 | Console.WriteLine(eee.Message); 87 | using StreamReader sr = new StreamReader(eee.Response.GetResponseStream()); 88 | Console.WriteLine(sr.ReadToEnd()); 89 | await MessageManager.SendFriendMessageAsync(q, "获取解释出错"); 90 | } 91 | return true; 92 | } 93 | return false; 94 | } 95 | 96 | public async Task GroupMessage(GroupMessageReceiver e) { 97 | string text = Utils.GetMessageText(e.MessageChain); 98 | string q = e.Sender.Group.Id; 99 | 100 | if (Regex.IsMatch(text, @"^.{1,20}是啥。。。$")) { 101 | if (DateTime.Now < Cooldown) { 102 | await MessageManager.SendGroupMessageAsync(q, "功能正在冷却,请稍后再试"); 103 | return true; 104 | } 105 | 106 | text = text[..^5]; 107 | try { 108 | var o = new { 109 | phrase = text, 110 | page = 1 111 | }; 112 | 113 | string json = JsonConvert.SerializeObject(o, Formatting.None); 114 | Console.WriteLine(json); 115 | 116 | string resp = await "https://api.jikipedia.com/go/search_entities" 117 | .WithHeader("Content-Type", "application/json;charset=utf-8") 118 | .WithHeader("Client", "web") 119 | .WithHeader("Client-Version", "2.7.2k") 120 | .WithHeader("XID", GenerateXID()) 121 | .PostJsonAsync(o) 122 | .ReceiveString(); 123 | 124 | JObject responceJson = JObject.Parse(resp); 125 | 126 | JArray dataArray = (JArray) responceJson["data"]; 127 | 128 | foreach (var dat in dataArray) { 129 | if (dat["category"].ToString() == "definition") { 130 | string name = dat["definitions"][0]["term"]["title"].ToString(); 131 | string def = dat["definitions"][0]["content"].ToString(); 132 | 133 | //中括号去除 134 | def = Regex.Replace(def, @"\[.+(,.+)*:(?.+)\]", "${str}"); 135 | 136 | await MessageManager.SendGroupMessageAsync(q, $"可能的全名:{name}\n释义:{def}\n详细信息:https://jikipedia.com/search?phrase={HttpUtility.UrlEncode(text)}"); 137 | 138 | //添加全局冷却 139 | Cooldown = DateTime.Now.AddMinutes(0.5); 140 | 141 | return true; 142 | } 143 | } 144 | await MessageManager.SendGroupMessageAsync(q, "未找到解释!"); 145 | } catch (WebException eee) { 146 | if (((HttpWebResponse) eee.Response).StatusCode == HttpStatusCode.Locked) { 147 | Cooldown = DateTime.Now.AddMinutes(5.0); 148 | await MessageManager.SendGroupMessageAsync(q, "请求次数过多,请稍后再试"); 149 | return true; 150 | } 151 | 152 | Console.WriteLine(eee.Message); 153 | using StreamReader sr = new StreamReader(eee.Response.GetResponseStream()); 154 | Console.WriteLine(sr.ReadToEnd()); 155 | await MessageManager.SendGroupMessageAsync(q, "获取解释出错"); 156 | } 157 | return true; 158 | } 159 | return false; 160 | } 161 | 162 | private static string GenerateXID() { 163 | //random guid 164 | string content = "jikipedia_xid_5ea1338b-2d8d-435d-b04d-0a5d9e41d147"; 165 | //fixed version info 166 | string pwd = "web_2.7.2k_12uh00]35#@(poj["; 167 | byte[] key = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(pwd)); 168 | 169 | //random iv 170 | byte[] iv = RandomNumberGenerator.GetBytes(16); 171 | var encrypted = EncryptStringToBytes_Aes(content, key, iv); 172 | 173 | byte[] resultbin = iv.Concat(encrypted).ToArray(); 174 | return Convert.ToBase64String(resultbin); 175 | } 176 | private static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV) { 177 | // Check arguments. 178 | if (plainText == null || plainText.Length <= 0) 179 | throw new ArgumentNullException("plainText"); 180 | if (Key == null || Key.Length <= 0) 181 | throw new ArgumentNullException("Key"); 182 | if (IV == null || IV.Length <= 0) 183 | throw new ArgumentNullException("IV"); 184 | byte[] encrypted; 185 | // Create an Aes object 186 | // with the specified key and IV. 187 | using (Aes aesAlg = Aes.Create()) { 188 | aesAlg.Key = Key; 189 | aesAlg.IV = IV; 190 | 191 | aesAlg.Padding = PaddingMode.PKCS7; 192 | aesAlg.Mode = CipherMode.CBC; 193 | 194 | // Create a decrytor to perform the stream transform. 195 | ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); 196 | 197 | // Create the streams used for encryption. 198 | using (MemoryStream msEncrypt = new MemoryStream()) { 199 | using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { 200 | using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) { 201 | 202 | //Write all data to the stream. 203 | swEncrypt.Write(plainText); 204 | } 205 | encrypted = msEncrypt.ToArray(); 206 | } 207 | } 208 | } 209 | // Return the encrypted bytes from the memory stream. 210 | return encrypted; 211 | } 212 | } 213 | } -------------------------------------------------------------------------------- /LQ1Bot/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reactive.Linq; 4 | using System.Text.RegularExpressions; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using LQ1Bot.Interface; 8 | using LQ1Bot.Plugins; 9 | using LQ1Bot.Secret; 10 | using Mirai.Net.Data.Messages.Receivers; 11 | using Mirai.Net.Sessions; 12 | using Mirai.Net.Sessions.Http.Managers; 13 | using Mirai.Net.Utils.Scaffolds; 14 | 15 | namespace LQ1Bot { 16 | 17 | internal class Program { 18 | public static LQ1BotConfig Secret; 19 | 20 | private static async Task Main(string[] args) { 21 | Secret = new LQ1BotConfig(); 22 | Secret.Init(); 23 | 24 | using var bot = new MiraiBot { 25 | Address = Secret.MiraiIp + ":" + Secret.MiraiPort, 26 | QQ = Secret.QQ.ToString(), 27 | VerifyKey = Secret.MiraiSecret 28 | }; 29 | 30 | await bot.LaunchAsync(); 31 | Console.WriteLine("已成功连接至Mirai"); 32 | 33 | //命令行参数发送群消息 34 | if (args.Length > 0) { 35 | switch (args[0]) { 36 | case "-sg": 37 | if (args.Length > 2) { 38 | long group = long.Parse(args[1]); 39 | string msg = args[2]; 40 | Console.WriteLine($"群号:{group}\t消息内容:{msg}"); 41 | var match = Regex.Match(msg, @"(?.+)@(?\d+)$"); 42 | if (match.Length > 1) { 43 | await MessageManager.SendGroupMessageAsync(group.ToString(), new MessageChainBuilder() 44 | .Plain(match.Groups["msg"].ToString()) 45 | .At(match.Groups["qq"].ToString()) 46 | .Build()); 47 | } else { 48 | await MessageManager.SendGroupMessageAsync(group.ToString(), msg); 49 | } 50 | Console.WriteLine("发送成功"); 51 | Environment.Exit(0); 52 | } 53 | break; 54 | case "-sf": 55 | if (args.Length > 2) { 56 | long qq = long.Parse(args[1]); 57 | string msg = args[2]; 58 | Console.WriteLine($"好友QQ号:{qq}\t消息内容:{msg}"); 59 | await MessageManager.SendFriendMessageAsync(qq.ToString(), msg); 60 | Console.WriteLine("发送成功"); 61 | Environment.Exit(0); 62 | } 63 | break; 64 | } 65 | } 66 | 67 | 68 | //特殊定制功能就不公开了 69 | SpecialFunction sf = new SpecialFunction(Secret, bot); 70 | 71 | PluginController Controller = new PluginController(); 72 | Controller.LoadPlugins(); 73 | 74 | LQ1Bot plugin = new LQ1Bot(Secret, bot); 75 | 76 | bot.MessageReceived 77 | .OfType() 78 | .Subscribe(async receiver => { 79 | if (!await sf.GroupMessage(receiver)) { 80 | new Thread(new ThreadStart(async () => { 81 | bool result = false; 82 | foreach (var v in PluginController.PluginInstance.OrderByDescending(o => o.Priority)) { 83 | if (v is IGroupMessage) { 84 | if (!v.CanDisable || FunctionSwitch.IsEnabled(long.Parse(receiver.Sender.Group.Id), v.PluginName)) { 85 | try { 86 | result = await ((IGroupMessage) v).GroupMessage(receiver); 87 | if (result) { 88 | break; 89 | } 90 | } catch (Exception e) { 91 | Console.Error.WriteLine(e); 92 | } 93 | } 94 | } 95 | } 96 | })).Start(); 97 | } 98 | }); 99 | 100 | bot.MessageReceived 101 | .OfType() 102 | .Subscribe(async receiver => { 103 | if (!await sf.FriendMessage(receiver)) { 104 | new Thread(new ThreadStart(async () => { 105 | bool result = false; 106 | foreach (var v in PluginController.PluginInstance.OrderByDescending(o => o.Priority)) { 107 | if (v is IFriendMessage message) { 108 | try { 109 | result = await message.FriendMessage(receiver); 110 | if (result) { 111 | break; 112 | } 113 | } catch (Exception e) { 114 | Console.Error.WriteLine(e); 115 | } 116 | } 117 | } 118 | })).Start(); 119 | } 120 | }); 121 | 122 | bot.DisconnectionHappened 123 | .Subscribe(async status => { 124 | Console.WriteLine("掉线重连中"); 125 | while (true) { 126 | try { 127 | await bot.LaunchAsync(); 128 | break; 129 | } catch (Exception e) { 130 | Console.Error.WriteLine(e.Message); 131 | } 132 | } 133 | Console.WriteLine("重连成功"); 134 | }); 135 | 136 | //控制台指令 137 | while (true) { 138 | string temp = await Console.In.ReadLineAsync(); 139 | if (temp == "exit") { 140 | return; 141 | } 142 | if (temp == "plugins") { 143 | Controller.ShowPlugins(); 144 | } 145 | if (Regex.IsMatch(temp, @"^send \d+ .+$")) { 146 | long q = long.Parse(temp.Split(' ')[1]); 147 | string msg = temp.Split(' ')[2]; 148 | await MessageManager.SendGroupMessageAsync(q.ToString(), msg); 149 | } 150 | if (Regex.IsMatch(temp, @"^spam \d+ \d+ .+$")) { 151 | long q = long.Parse(temp.Split(' ')[1]); 152 | string msg = temp.Split(' ')[3]; 153 | int count = int.Parse(temp.Split(' ')[2]); 154 | for (int i = 0; i < count; i++) { 155 | await MessageManager.SendGroupMessageAsync(q.ToString(), msg); 156 | } 157 | } 158 | } 159 | } 160 | } 161 | } -------------------------------------------------------------------------------- /LQ1Bot/Utils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Security.Cryptography; 5 | using System.Text; 6 | using Mirai.Net.Data.Messages; 7 | using Mirai.Net.Data.Messages.Concretes; 8 | 9 | namespace LQ1Bot { 10 | 11 | internal static class Utils { 12 | 13 | /// 14 | /// 获取一个类在其所在的程序集中的所有子类 15 | /// 16 | /// 给定的类型 17 | /// 所有子类 18 | public static List GetSubClass(Type ParentType) { 19 | var SubTypeList = new List(); 20 | var Assembly = ParentType.Assembly; 21 | var AssemblyAllTypes = Assembly.GetTypes(); 22 | foreach (var ItemType in AssemblyAllTypes) { 23 | if (ItemType.BaseType?.Name == ParentType.Name) { 24 | SubTypeList.Add(ItemType); 25 | } 26 | } 27 | return SubTypeList.ToList(); 28 | } 29 | 30 | public static string GetMessageText(IEnumerable msg) { 31 | string text = ""; 32 | foreach (var v in msg) { 33 | //text += "\n" + v.Type; 34 | switch (v.Type) { 35 | case Messages.Plain: 36 | text += ((PlainMessage) v).Text; 37 | break; 38 | 39 | case Messages.At: 40 | AtMessage am = (AtMessage) v; 41 | text += am.Target; 42 | break; 43 | //case "Quote": 44 | // QuoteMessage qm = (QuoteMessage) v; 45 | // var oc = qm.OriginChain; 46 | // //text += qm.; 47 | // break; 48 | //case "Source": 49 | //SourceMessage sm = (SourceMessage) v; 50 | } 51 | } 52 | return text; 53 | } 54 | 55 | /// 56 | /// MD5加密(32位) 57 | /// 58 | /// 加密字符 59 | /// 60 | public static string GetMD5(string str) { 61 | MD5 md5 = MD5.Create(); 62 | // 将字符串转换成字节数组 63 | byte[] byteOld = Encoding.UTF8.GetBytes(str); 64 | // 调用加密方法 65 | byte[] byteNew = md5.ComputeHash(byteOld); 66 | // 将加密结果转换为字符串 67 | StringBuilder sb = new StringBuilder(); 68 | foreach (byte b in byteNew) { 69 | // 将字节转换成16进制表示的字符串, 70 | sb.Append(b.ToString("x2")); 71 | } 72 | // 返回加密的字符串 73 | return sb.ToString(); 74 | } 75 | 76 | /// 77 | /// 强随机字符串生成 78 | /// 79 | /// 字符串长度 80 | /// 填充字符 81 | /// 82 | public static string GetStrongRandomString(int Length, string Pattern = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") { 83 | if (Length < 1 || Pattern.Length < 2) return null; 84 | StringBuilder sb = new StringBuilder(); 85 | for (int i = 0; i < Length; i++) { 86 | sb.Append(Pattern[RandomNumberGenerator.GetInt32(Pattern.Length)]); 87 | } 88 | return sb.ToString(); 89 | } 90 | 91 | public static string RandomMsg(params string[] s) { 92 | Random r = new Random(); 93 | return s[(int) Math.Round(r.NextDouble() * (s.Length - 1))]; 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Light_Quanta[1]; Bot 2 | 3 | Light_Quanta[1];整活bot 4 | 5 | **注:本项目已经停更,请查看重置版[LQ2Bot](https://github.com/LightQuanta/LQ2Bot/)** 6 | 7 | 8 | ## 特性 9 | 10 | - 各种究极整活功能,保证群聊瞬间99+( 11 | - 自助禁言,满足群友抖m需求 12 | - 各种稀奇古怪的抽奖功能,鉴定欧皇 13 | - 由Light_Quanta进行维护,随时添加群友的新点子( 14 | ## 使用帮助 15 | 16 | [看这里](https://lq0.tech/bot) 17 | 18 | 19 | 20 | 21 | ## 部署 22 | 23 | ~~为什么会有人想部署这么屑的Bot~~ 24 | 25 | 如果你想自己部署此bot的话 26 | 27 | ~~此Bot基于[Mirai-CSharp](https://github.com/Executor-Cheng/Mirai-CSharp)~~ 28 | 29 | 现版本基于[Mirai.Net](https://github.com/SinoAHpx/Mirai.Net)开发 30 | 31 | ~~问就是Mirai-CSharp新版我没看懂怎么用~~ 32 | 33 | 运行环境为.Net Core 3.1 34 | 35 | 使用了以下NuGet程序包 36 | 37 | > Microsoft.EntityFrameworkCore.Sqlite 38 | 39 | > Mirai.Net 40 | 41 | > Newtonsoft.Json 42 | 43 | > TinyPinyin.Net 44 | 45 | 自己部署时记得删除`Program.cs`里和`SpecialFunction`相关的代码 46 | 47 | 48 | ## 开源协议 49 | 50 | 本程序采用AGPL-3.0协议进行授权 51 | 52 | 53 | --------------------------------------------------------------------------------