commit
9e05e69cfb
4
.gitignore
vendored
4
.gitignore
vendored
@ -37,3 +37,7 @@ Tests/bin
|
|||||||
NadekoBot/bin/Debug/data/nadekobot.sqlite
|
NadekoBot/bin/Debug/data/nadekobot.sqlite
|
||||||
NadekoBot/bin/Debug/data/config.json
|
NadekoBot/bin/Debug/data/config.json
|
||||||
NadekoBot/bin/Debug/data/ServerSpecificConfigs.json
|
NadekoBot/bin/Debug/data/ServerSpecificConfigs.json
|
||||||
|
NadekoBot.sln.iml
|
||||||
|
.idea/workspace.xml
|
||||||
|
.idea/vcs.xml
|
||||||
|
.idea/modules.xml
|
@ -41,32 +41,32 @@ Global
|
|||||||
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU
|
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.FullDebug|Any CPU.Build.0 = Debug|Any CPU
|
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.FullDebug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.NadekoRelease|Any CPU.ActiveCfg = NadekoRelease|Any CPU
|
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.NadekoRelease|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.NadekoRelease|Any CPU.Build.0 = NadekoRelease|Any CPU
|
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.NadekoRelease|Any CPU.Build.0 = Release|Any CPU
|
||||||
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{8D71A857-879A-4A10-859E-5FF824ED6688}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU
|
{8D71A857-879A-4A10-859E-5FF824ED6688}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{8D71A857-879A-4A10-859E-5FF824ED6688}.FullDebug|Any CPU.Build.0 = Debug|Any CPU
|
{8D71A857-879A-4A10-859E-5FF824ED6688}.FullDebug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{8D71A857-879A-4A10-859E-5FF824ED6688}.NadekoRelease|Any CPU.ActiveCfg = NadekoRelease|Any CPU
|
{8D71A857-879A-4A10-859E-5FF824ED6688}.NadekoRelease|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{8D71A857-879A-4A10-859E-5FF824ED6688}.NadekoRelease|Any CPU.Build.0 = NadekoRelease|Any CPU
|
{8D71A857-879A-4A10-859E-5FF824ED6688}.NadekoRelease|Any CPU.Build.0 = Release|Any CPU
|
||||||
{8D71A857-879A-4A10-859E-5FF824ED6688}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{8D71A857-879A-4A10-859E-5FF824ED6688}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{8D71A857-879A-4A10-859E-5FF824ED6688}.Release|Any CPU.Build.0 = Release|Any CPU
|
{8D71A857-879A-4A10-859E-5FF824ED6688}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{3091164F-66AE-4543-A63D-167C1116241D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{3091164F-66AE-4543-A63D-167C1116241D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{3091164F-66AE-4543-A63D-167C1116241D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{3091164F-66AE-4543-A63D-167C1116241D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU
|
{3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|Any CPU.Build.0 = Debug|Any CPU
|
{3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{3091164F-66AE-4543-A63D-167C1116241D}.NadekoRelease|Any CPU.ActiveCfg = NadekoRelease|Any CPU
|
{3091164F-66AE-4543-A63D-167C1116241D}.NadekoRelease|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{3091164F-66AE-4543-A63D-167C1116241D}.NadekoRelease|Any CPU.Build.0 = NadekoRelease|Any CPU
|
{3091164F-66AE-4543-A63D-167C1116241D}.NadekoRelease|Any CPU.Build.0 = Release|Any CPU
|
||||||
{3091164F-66AE-4543-A63D-167C1116241D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{3091164F-66AE-4543-A63D-167C1116241D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{3091164F-66AE-4543-A63D-167C1116241D}.Release|Any CPU.Build.0 = Release|Any CPU
|
{3091164F-66AE-4543-A63D-167C1116241D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU
|
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|Any CPU.Build.0 = Debug|Any CPU
|
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.NadekoRelease|Any CPU.ActiveCfg = NadekoRelease|Any CPU
|
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.NadekoRelease|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.NadekoRelease|Any CPU.Build.0 = NadekoRelease|Any CPU
|
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.NadekoRelease|Any CPU.Build.0 = Release|Any CPU
|
||||||
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|Any CPU.Build.0 = Release|Any CPU
|
{1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{45B2545D-C612-4919-B34C-D65EA1371C51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{45B2545D-C612-4919-B34C-D65EA1371C51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
@ -32,7 +32,16 @@ namespace NadekoBot.Classes
|
|||||||
conn.CreateTable<SongInfo>();
|
conn.CreateTable<SongInfo>();
|
||||||
conn.CreateTable<PlaylistSongInfo>();
|
conn.CreateTable<PlaylistSongInfo>();
|
||||||
conn.CreateTable<MusicPlaylist>();
|
conn.CreateTable<MusicPlaylist>();
|
||||||
|
conn.CreateTable<Incident>();
|
||||||
conn.Execute(Queries.TransactionTriggerQuery);
|
conn.Execute(Queries.TransactionTriggerQuery);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
conn.Execute(Queries.DeletePlaylistTriggerQuery);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +103,14 @@ namespace NadekoBot.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void UpdateAll<T>(IEnumerable<T> objs) where T : IDataModel
|
||||||
|
{
|
||||||
|
using (var conn = new SQLiteConnection(FilePath))
|
||||||
|
{
|
||||||
|
conn.UpdateAll(objs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal HashSet<T> GetAllRows<T>() where T : IDataModel, new()
|
internal HashSet<T> GetAllRows<T>() where T : IDataModel, new()
|
||||||
{
|
{
|
||||||
using (var conn = new SQLiteConnection(FilePath))
|
using (var conn = new SQLiteConnection(FilePath))
|
||||||
@ -181,7 +198,7 @@ Limit 20 OFFSET ?", num * 20);
|
|||||||
{
|
{
|
||||||
using (var conn = new SQLiteConnection(FilePath))
|
using (var conn = new SQLiteConnection(FilePath))
|
||||||
{
|
{
|
||||||
return conn.Table<CurrencyState>().Take(n).ToList().OrderBy(cs => -cs.Value);
|
return conn.Table<CurrencyState>().OrderBy(cs => -cs.Value).Take(n).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,7 +214,7 @@ public class PlaylistData
|
|||||||
|
|
||||||
public static class Queries
|
public static class Queries
|
||||||
{
|
{
|
||||||
public static string TransactionTriggerQuery = @"
|
public const string TransactionTriggerQuery = @"
|
||||||
CREATE TRIGGER IF NOT EXISTS OnTransactionAdded
|
CREATE TRIGGER IF NOT EXISTS OnTransactionAdded
|
||||||
AFTER INSERT ON CurrencyTransaction
|
AFTER INSERT ON CurrencyTransaction
|
||||||
BEGIN
|
BEGIN
|
||||||
@ -208,4 +225,11 @@ INSERT OR REPLACE INTO CurrencyState (Id, UserId, Value, DateAdded)
|
|||||||
NEW.DateAdded);
|
NEW.DateAdded);
|
||||||
END
|
END
|
||||||
";
|
";
|
||||||
|
public const string DeletePlaylistTriggerQuery = @"
|
||||||
|
CREATE TRIGGER IF NOT EXISTS music_playlist
|
||||||
|
AFTER DELETE ON MusicPlaylist
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
DELETE FROM PlaylistSongInfo WHERE PlaylistId = OLD.Id;
|
||||||
|
END";
|
||||||
}
|
}
|
||||||
|
@ -352,5 +352,15 @@ namespace NadekoBot.Extensions
|
|||||||
await Task.Run(() => images.Merge(reverseScaleFactor)).ConfigureAwait(false);
|
await Task.Run(() => images.Merge(reverseScaleFactor)).ConfigureAwait(false);
|
||||||
|
|
||||||
public static string Unmention(this string str) => str.Replace("@", "ම");
|
public static string Unmention(this string str) => str.Replace("@", "ම");
|
||||||
|
|
||||||
|
public static Stream ToStream(this string str)
|
||||||
|
{
|
||||||
|
var sw = new StreamWriter(new MemoryStream());
|
||||||
|
sw.Write(str);
|
||||||
|
sw.Flush();
|
||||||
|
sw.BaseStream.Position = 0;
|
||||||
|
return sw.BaseStream;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,25 @@
|
|||||||
using System;
|
using NadekoBot.DataModels;
|
||||||
using System.IO;
|
using System;
|
||||||
|
|
||||||
namespace NadekoBot.Classes {
|
namespace NadekoBot.Classes
|
||||||
internal static class IncidentsHandler {
|
{
|
||||||
public static void Add(ulong serverId, string text) {
|
internal static class IncidentsHandler
|
||||||
Directory.CreateDirectory("data/incidents");
|
{
|
||||||
File.AppendAllText($"data/incidents/{serverId}.txt", text + "\n--------------------------\n");
|
public static void Add(ulong serverId, ulong channelId, string text)
|
||||||
|
{
|
||||||
var def = Console.ForegroundColor;
|
var def = Console.ForegroundColor;
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
Console.WriteLine($"INCIDENT: {text}");
|
Console.WriteLine($"INCIDENT: {text}");
|
||||||
Console.ForegroundColor = def;
|
Console.ForegroundColor = def;
|
||||||
|
var incident = new Incident
|
||||||
|
{
|
||||||
|
ChannelId = (long)channelId,
|
||||||
|
ServerId = (long)serverId,
|
||||||
|
Text = text,
|
||||||
|
Read = false
|
||||||
|
};
|
||||||
|
|
||||||
|
DbHandler.Instance.InsertData<Incident>(incident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
204
NadekoBot/Classes/ObservableConcurrentDictionary.cs
Normal file
204
NadekoBot/Classes/ObservableConcurrentDictionary.cs
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
//--------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
//
|
||||||
|
// File: ObservableConcurrentDictionary.cs
|
||||||
|
//
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace System.Collections.Concurrent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a thread-safe dictionary for use with data binding.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey">Specifies the type of the keys in this collection.</typeparam>
|
||||||
|
/// <typeparam name="TValue">Specifies the type of the values in this collection.</typeparam>
|
||||||
|
[DebuggerDisplay("Count={Count}")]
|
||||||
|
public class ObservableConcurrentDictionary<TKey, TValue> :
|
||||||
|
ICollection<KeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue>,
|
||||||
|
INotifyCollectionChanged, INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private readonly SynchronizationContext _context;
|
||||||
|
private readonly ConcurrentDictionary<TKey, TValue> _dictionary;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes an instance of the ObservableConcurrentDictionary class.
|
||||||
|
/// </summary>
|
||||||
|
public ObservableConcurrentDictionary()
|
||||||
|
{
|
||||||
|
_context = AsyncOperationManager.SynchronizationContext;
|
||||||
|
_dictionary = new ConcurrentDictionary<TKey, TValue>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Event raised when the collection changes.</summary>
|
||||||
|
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||||
|
/// <summary>Event raised when a property on the collection changes.</summary>
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Notifies observers of CollectionChanged or PropertyChanged of an update to the dictionary.
|
||||||
|
/// </summary>
|
||||||
|
private void NotifyObserversOfChange()
|
||||||
|
{
|
||||||
|
var collectionHandler = CollectionChanged;
|
||||||
|
var propertyHandler = PropertyChanged;
|
||||||
|
if (collectionHandler != null || propertyHandler != null)
|
||||||
|
{
|
||||||
|
_context.Post(s =>
|
||||||
|
{
|
||||||
|
if (collectionHandler != null)
|
||||||
|
{
|
||||||
|
collectionHandler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||||
|
}
|
||||||
|
if (propertyHandler != null)
|
||||||
|
{
|
||||||
|
propertyHandler(this, new PropertyChangedEventArgs("Count"));
|
||||||
|
propertyHandler(this, new PropertyChangedEventArgs("Keys"));
|
||||||
|
propertyHandler(this, new PropertyChangedEventArgs("Values"));
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Attempts to add an item to the dictionary, notifying observers of any changes.</summary>
|
||||||
|
/// <param name="item">The item to be added.</param>
|
||||||
|
/// <returns>Whether the add was successful.</returns>
|
||||||
|
private bool TryAddWithNotification(KeyValuePair<TKey, TValue> item)
|
||||||
|
{
|
||||||
|
return TryAddWithNotification(item.Key, item.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Attempts to add an item to the dictionary, notifying observers of any changes.</summary>
|
||||||
|
/// <param name="key">The key of the item to be added.</param>
|
||||||
|
/// <param name="value">The value of the item to be added.</param>
|
||||||
|
/// <returns>Whether the add was successful.</returns>
|
||||||
|
private bool TryAddWithNotification(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
bool result = _dictionary.TryAdd(key, value);
|
||||||
|
if (result) NotifyObserversOfChange();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Attempts to remove an item from the dictionary, notifying observers of any changes.</summary>
|
||||||
|
/// <param name="key">The key of the item to be removed.</param>
|
||||||
|
/// <param name="value">The value of the item removed.</param>
|
||||||
|
/// <returns>Whether the removal was successful.</returns>
|
||||||
|
private bool TryRemoveWithNotification(TKey key, out TValue value)
|
||||||
|
{
|
||||||
|
bool result = _dictionary.TryRemove(key, out value);
|
||||||
|
if (result) NotifyObserversOfChange();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Attempts to add or update an item in the dictionary, notifying observers of any changes.</summary>
|
||||||
|
/// <param name="key">The key of the item to be updated.</param>
|
||||||
|
/// <param name="value">The new value to set for the item.</param>
|
||||||
|
/// <returns>Whether the update was successful.</returns>
|
||||||
|
private void UpdateWithNotification(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
_dictionary[key] = value;
|
||||||
|
NotifyObserversOfChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ICollection<KeyValuePair<TKey,TValue>> Members
|
||||||
|
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
||||||
|
{
|
||||||
|
TryAddWithNotification(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
|
||||||
|
{
|
||||||
|
((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Clear();
|
||||||
|
NotifyObserversOfChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||||||
|
{
|
||||||
|
return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Contains(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).CopyTo(array, arrayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ICollection<KeyValuePair<TKey, TValue>>.Count {
|
||||||
|
get { return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly {
|
||||||
|
get { return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).IsReadOnly; }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||||
|
{
|
||||||
|
TValue temp;
|
||||||
|
return TryRemoveWithNotification(item.Key, out temp);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
|
||||||
|
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
|
||||||
|
{
|
||||||
|
return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).GetEnumerator();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDictionary<TKey,TValue> Members
|
||||||
|
public void Add(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
TryAddWithNotification(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ContainsKey(TKey key)
|
||||||
|
{
|
||||||
|
return _dictionary.ContainsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICollection<TKey> Keys {
|
||||||
|
get { return _dictionary.Keys; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Remove(TKey key)
|
||||||
|
{
|
||||||
|
TValue temp;
|
||||||
|
return TryRemoveWithNotification(key, out temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryGetValue(TKey key, out TValue value)
|
||||||
|
{
|
||||||
|
return _dictionary.TryGetValue(key, out value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryAdd(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
return TryAddWithNotification(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ICollection<TValue> Values {
|
||||||
|
get { return _dictionary.Values; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public TValue this[TKey key] {
|
||||||
|
get { return _dictionary[key]; }
|
||||||
|
set { UpdateWithNotification(key, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryRemove(TKey key, out TValue value)
|
||||||
|
{
|
||||||
|
return TryRemoveWithNotification(key, out value);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
@ -176,6 +176,33 @@ namespace NadekoBot.Classes
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task<string> GetRelatedVideoId(string id)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(id))
|
||||||
|
throw new ArgumentNullException(nameof(id));
|
||||||
|
var match = new Regex("(?:youtu\\.be\\/|v=)(?<id>[\\da-zA-Z\\-_]*)").Match(id);
|
||||||
|
if (match.Length > 1)
|
||||||
|
{
|
||||||
|
id = match.Groups["id"].Value;
|
||||||
|
}
|
||||||
|
var response = await GetResponseStringAsync(
|
||||||
|
$"https://www.googleapis.com/youtube/v3/search?" +
|
||||||
|
$"part=snippet&maxResults=1&type=video" +
|
||||||
|
$"&relatedToVideoId={id}" +
|
||||||
|
$"&key={NadekoBot.Creds.GoogleAPIKey}").ConfigureAwait(false);
|
||||||
|
JObject obj = JObject.Parse(response);
|
||||||
|
|
||||||
|
var data = JsonConvert.DeserializeObject<YoutubeVideoSearch>(response);
|
||||||
|
|
||||||
|
if (data.items.Length > 0)
|
||||||
|
{
|
||||||
|
var toReturn = "http://www.youtube.com/watch?v=" + data.items[0].id.videoId.ToString();
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<string> GetPlaylistIdByKeyword(string query)
|
public static async Task<string> GetPlaylistIdByKeyword(string query)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(NadekoBot.Creds.GoogleAPIKey))
|
if (string.IsNullOrWhiteSpace(NadekoBot.Creds.GoogleAPIKey))
|
||||||
@ -350,5 +377,13 @@ namespace NadekoBot.Classes
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string ShowInPrettyCode<T>(IEnumerable<T> items, Func<T, string> howToPrint, int cols = 3)
|
||||||
|
{
|
||||||
|
var i = 0;
|
||||||
|
return "```xl\n" + string.Join("\n", items.GroupBy(item => (i++) / cols)
|
||||||
|
.Select(ig => string.Join("", ig.Select(el => howToPrint(el)))))
|
||||||
|
+ $"\n```";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@ namespace NadekoBot.Classes
|
|||||||
get { return voicePlusTextEnabled; }
|
get { return voicePlusTextEnabled; }
|
||||||
set {
|
set {
|
||||||
voicePlusTextEnabled = value;
|
voicePlusTextEnabled = value;
|
||||||
|
if (!SpecificConfigurations.Instantiated) return;
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,10 +77,50 @@ namespace NadekoBot.Classes
|
|||||||
get { return sendPrivateMessageOnMention; }
|
get { return sendPrivateMessageOnMention; }
|
||||||
set {
|
set {
|
||||||
sendPrivateMessageOnMention = value;
|
sendPrivateMessageOnMention = value;
|
||||||
|
if (!SpecificConfigurations.Instantiated) return;
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonProperty("LogChannel")]
|
||||||
|
private ulong? logServerChannel = null;
|
||||||
|
[JsonIgnore]
|
||||||
|
public ulong? LogServerChannel {
|
||||||
|
get { return logServerChannel; }
|
||||||
|
set {
|
||||||
|
logServerChannel = value;
|
||||||
|
if (!SpecificConfigurations.Instantiated) return;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonProperty("LogPresenceChannel")]
|
||||||
|
private ulong? logPresenceChannel = null;
|
||||||
|
[JsonIgnore]
|
||||||
|
public ulong? LogPresenceChannel {
|
||||||
|
get { return logPresenceChannel; }
|
||||||
|
set {
|
||||||
|
logPresenceChannel = value;
|
||||||
|
if (!SpecificConfigurations.Instantiated) return;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
private ObservableConcurrentDictionary<ulong, ulong> voiceChannelLog;
|
||||||
|
public ObservableConcurrentDictionary<ulong, ulong> VoiceChannelLog {
|
||||||
|
get { return voiceChannelLog; }
|
||||||
|
set {
|
||||||
|
voiceChannelLog = value;
|
||||||
|
if (value != null)
|
||||||
|
voiceChannelLog.CollectionChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
if (!SpecificConfigurations.Instantiated) return;
|
||||||
|
OnPropertyChanged();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
private ObservableCollection<ulong> listOfSelfAssignableRoles;
|
private ObservableCollection<ulong> listOfSelfAssignableRoles;
|
||||||
public ObservableCollection<ulong> ListOfSelfAssignableRoles {
|
public ObservableCollection<ulong> ListOfSelfAssignableRoles {
|
||||||
@ -106,6 +147,33 @@ namespace NadekoBot.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
private ObservableCollection<ulong> generateCurrencyChannels;
|
||||||
|
public ObservableCollection<ulong> GenerateCurrencyChannels {
|
||||||
|
get { return generateCurrencyChannels; }
|
||||||
|
set {
|
||||||
|
generateCurrencyChannels = value;
|
||||||
|
if (value != null)
|
||||||
|
generateCurrencyChannels.CollectionChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
if (!SpecificConfigurations.Instantiated) return;
|
||||||
|
OnPropertyChanged();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
private bool autoDeleteMessagesOnCommand = false;
|
||||||
|
public bool AutoDeleteMessagesOnCommand {
|
||||||
|
get { return autoDeleteMessagesOnCommand; }
|
||||||
|
set {
|
||||||
|
autoDeleteMessagesOnCommand = value;
|
||||||
|
if (!SpecificConfigurations.Instantiated) return;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
private ObservableCollection<StreamNotificationConfig> observingStreams;
|
private ObservableCollection<StreamNotificationConfig> observingStreams;
|
||||||
public ObservableCollection<StreamNotificationConfig> ObservingStreams {
|
public ObservableCollection<StreamNotificationConfig> ObservingStreams {
|
||||||
@ -121,10 +189,23 @@ namespace NadekoBot.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
private float defaultMusicVolume = 1f;
|
||||||
|
public float DefaultMusicVolume {
|
||||||
|
get { return defaultMusicVolume; }
|
||||||
|
set {
|
||||||
|
defaultMusicVolume = value;
|
||||||
|
if (!SpecificConfigurations.Instantiated) return;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ServerSpecificConfig()
|
public ServerSpecificConfig()
|
||||||
{
|
{
|
||||||
ListOfSelfAssignableRoles = new ObservableCollection<ulong>();
|
ListOfSelfAssignableRoles = new ObservableCollection<ulong>();
|
||||||
ObservingStreams = new ObservableCollection<StreamNotificationConfig>();
|
ObservingStreams = new ObservableCollection<StreamNotificationConfig>();
|
||||||
|
GenerateCurrencyChannels = new ObservableCollection<ulong>();
|
||||||
|
VoiceChannelLog = new ObservableConcurrentDictionary<ulong, ulong>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged = delegate { SpecificConfigurations.Default.Save(); };
|
public event PropertyChangedEventHandler PropertyChanged = delegate { SpecificConfigurations.Default.Save(); };
|
||||||
|
@ -6,8 +6,11 @@ using NadekoBot.DataModels;
|
|||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Administration.Commands;
|
using NadekoBot.Modules.Administration.Commands;
|
||||||
using NadekoBot.Modules.Permissions.Classes;
|
using NadekoBot.Modules.Permissions.Classes;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
@ -24,11 +27,26 @@ namespace NadekoBot.Modules.Administration
|
|||||||
commands.Add(new VoicePlusTextCommand(this));
|
commands.Add(new VoicePlusTextCommand(this));
|
||||||
commands.Add(new CrossServerTextChannel(this));
|
commands.Add(new CrossServerTextChannel(this));
|
||||||
commands.Add(new SelfAssignedRolesCommand(this));
|
commands.Add(new SelfAssignedRolesCommand(this));
|
||||||
commands.Add(new Remind(this));
|
|
||||||
commands.Add(new InfoCommands(this));
|
|
||||||
commands.Add(new CustomReactionsCommands(this));
|
commands.Add(new CustomReactionsCommands(this));
|
||||||
commands.Add(new AutoAssignRole(this));
|
commands.Add(new AutoAssignRole(this));
|
||||||
commands.Add(new SelfCommands(this));
|
commands.Add(new SelfCommands(this));
|
||||||
|
commands.Add(new IncidentsCommands(this));
|
||||||
|
|
||||||
|
NadekoBot.Client.GetService<CommandService>().CommandExecuted += DeleteCommandMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeleteCommandMessage(object sender, CommandEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Server == null || e.Channel.IsPrivate)
|
||||||
|
return;
|
||||||
|
var conf = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||||
|
if (!conf.AutoDeleteMessagesOnCommand)
|
||||||
|
return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
e.Message.Delete();
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Administration;
|
public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Administration;
|
||||||
@ -45,6 +63,21 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
commands.ForEach(cmd => cmd.Init(cgb));
|
commands.ForEach(cmd => cmd.Init(cgb));
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "delmsgoncmd")
|
||||||
|
.Description("Toggles the automatic deletion of user's successful command message to prevent chat flood. Server Manager Only.")
|
||||||
|
.AddCheck(SimpleCheckers.ManageServer())
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var conf = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||||
|
conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand;
|
||||||
|
Classes.JSONModels.ConfigHandler.SaveConfig();
|
||||||
|
if (conf.AutoDeleteMessagesOnCommand)
|
||||||
|
await e.Channel.SendMessage("❗`Now automatically deleting successfull command invokations.`");
|
||||||
|
else
|
||||||
|
await e.Channel.SendMessage("❗`Stopped automatic deletion of successfull command invokations.`");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "restart")
|
cgb.CreateCommand(Prefix + "restart")
|
||||||
.Description("Restarts the bot. Might not work.")
|
.Description("Restarts the bot. Might not work.")
|
||||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||||
@ -262,25 +295,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "roles")
|
|
||||||
.Description("List all roles on this server or a single user if specified.")
|
|
||||||
.Parameter("user", ParameterType.Unparsed)
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrWhiteSpace(e.GetArg("user")))
|
|
||||||
{
|
|
||||||
var usr = e.Server.FindUsers(e.GetArg("user")).FirstOrDefault();
|
|
||||||
if (usr == null) return;
|
|
||||||
|
|
||||||
await e.Channel.SendMessage($"`List of roles for **{usr.Name}**:` \n• " + string.Join("\n• ", usr.Roles)).ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await e.Channel.SendMessage("`List of roles:` \n• " + string.Join("\n• ", e.Server.Roles)).ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "ban").Alias(Prefix + "b")
|
cgb.CreateCommand(Prefix + "ban").Alias(Prefix + "b")
|
||||||
.Parameter("user", ParameterType.Required)
|
.Parameter("user", ParameterType.Required)
|
||||||
.Parameter("msg", ParameterType.Optional)
|
.Parameter("msg", ParameterType.Unparsed)
|
||||||
.Description("Bans a user by id or name with an optional message.\n**Usage**: .b \"@some Guy\" Your behaviour is toxic.")
|
.Description("Bans a user by id or name with an optional message.\n**Usage**: .b \"@some Guy\" Your behaviour is toxic.")
|
||||||
.Do(async e =>
|
.Do(async e =>
|
||||||
{
|
{
|
||||||
@ -315,7 +332,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
cgb.CreateCommand(Prefix + "softban").Alias(Prefix + "sb")
|
cgb.CreateCommand(Prefix + "softban").Alias(Prefix + "sb")
|
||||||
.Parameter("user", ParameterType.Required)
|
.Parameter("user", ParameterType.Required)
|
||||||
.Parameter("msg", ParameterType.Optional)
|
.Parameter("msg", ParameterType.Unparsed)
|
||||||
.Description("Bans and then unbans a user by id or name with an optional message.\n**Usage**: .sb \"@some Guy\" Your behaviour is toxic.")
|
.Description("Bans and then unbans a user by id or name with an optional message.\n**Usage**: .sb \"@some Guy\" Your behaviour is toxic.")
|
||||||
.Do(async e =>
|
.Do(async e =>
|
||||||
{
|
{
|
||||||
@ -599,40 +616,6 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await e.Channel.SendMessage(":ok: **New channel name set.**").ConfigureAwait(false);
|
await e.Channel.SendMessage(":ok: **New channel name set.**").ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "userid").Alias(Prefix + "uid")
|
|
||||||
.Description("Shows user ID.")
|
|
||||||
.Parameter("user", ParameterType.Unparsed)
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
var usr = e.User;
|
|
||||||
if (!string.IsNullOrWhiteSpace(e.GetArg("user"))) usr = e.Channel.FindUsers(e.GetArg("user")).FirstOrDefault();
|
|
||||||
if (usr == null)
|
|
||||||
return;
|
|
||||||
await e.Channel.SendMessage($"Id of the user { usr.Name } is { usr.Id }").ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "channelid").Alias(Prefix + "cid")
|
|
||||||
.Description("Shows current channel ID.")
|
|
||||||
.Do(async e => await e.Channel.SendMessage("This channel's ID is " + e.Channel.Id).ConfigureAwait(false));
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "serverid").Alias(Prefix + "sid")
|
|
||||||
.Description("Shows current server ID.")
|
|
||||||
.Do(async e => await e.Channel.SendMessage("This server's ID is " + e.Server.Id).ConfigureAwait(false));
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "stats")
|
|
||||||
.Description("Shows some basic stats for Nadeko.")
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
await e.Channel.SendMessage(await NadekoStats.Instance.GetStats());
|
|
||||||
});
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "dysyd")
|
|
||||||
.Description("Shows some basic stats for Nadeko.")
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
await e.Channel.SendMessage((await NadekoStats.Instance.GetStats()).Matrix().TrimTo(1990)).ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "heap")
|
cgb.CreateCommand(Prefix + "heap")
|
||||||
.Description("Shows allocated memory - **Bot Owner Only!**")
|
.Description("Shows allocated memory - **Bot Owner Only!**")
|
||||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||||
@ -736,7 +719,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
cgb.CreateCommand(Prefix + "newavatar")
|
cgb.CreateCommand(Prefix + "newavatar")
|
||||||
.Alias(Prefix + "setavatar")
|
.Alias(Prefix + "setavatar")
|
||||||
.Description("Sets a new avatar image for the NadekoBot. **Bot Owner Only!**")
|
.Description("Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot Owner Only!**\n**Usage**: `.setavatar https://i.ytimg.com/vi/WDudkR1eTMM/maxresdefault.jpg`")
|
||||||
.Parameter("img", ParameterType.Unparsed)
|
.Parameter("img", ParameterType.Unparsed)
|
||||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||||
.Do(async e =>
|
.Do(async e =>
|
||||||
@ -766,80 +749,51 @@ namespace NadekoBot.Modules.Administration
|
|||||||
client.SetGame(e.GetArg("set_game"));
|
client.SetGame(e.GetArg("set_game"));
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "checkmyperms")
|
|
||||||
.Description("Checks your userspecific permissions on this channel.")
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
var output = "```\n";
|
|
||||||
foreach (var p in e.User.ServerPermissions.GetType().GetProperties().Where(p => !p.GetGetMethod().GetParameters().Any()))
|
|
||||||
{
|
|
||||||
output += p.Name + ": " + p.GetValue(e.User.ServerPermissions, null).ToString() + "\n";
|
|
||||||
}
|
|
||||||
output += "```";
|
|
||||||
await e.User.SendMessage(output).ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
Server commsServer = null;
|
|
||||||
User commsUser = null;
|
|
||||||
Channel commsChannel = null;
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "commsuser")
|
|
||||||
.Description("Sets a user for through-bot communication. Only works if server is set. Resets commschannel. **Bot Owner Only!**")
|
|
||||||
.Parameter("name", ParameterType.Unparsed)
|
|
||||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
commsUser = commsServer?.FindUsers(e.GetArg("name")).FirstOrDefault();
|
|
||||||
if (commsUser != null)
|
|
||||||
{
|
|
||||||
commsChannel = null;
|
|
||||||
await e.Channel.SendMessage("User for comms set.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
await e.Channel.SendMessage("No server specified or user.").ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "commsserver")
|
|
||||||
.Description("Sets a server for through-bot communication. **Bot Owner Only!**")
|
|
||||||
.Parameter("server", ParameterType.Unparsed)
|
|
||||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
commsServer = client.FindServers(e.GetArg("server")).FirstOrDefault();
|
|
||||||
if (commsServer != null)
|
|
||||||
await e.Channel.SendMessage("Server for comms set.").ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await e.Channel.SendMessage("No such server.").ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "commschannel")
|
|
||||||
.Description("Sets a channel for through-bot communication. Only works if server is set. Resets commsuser. **Bot Owner Only!**")
|
|
||||||
.Parameter("ch", ParameterType.Unparsed)
|
|
||||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
commsChannel = commsServer?.FindChannels(e.GetArg("ch"), ChannelType.Text).FirstOrDefault();
|
|
||||||
if (commsChannel != null)
|
|
||||||
{
|
|
||||||
commsUser = null;
|
|
||||||
await e.Channel.SendMessage("Server for comms set.").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
await e.Channel.SendMessage("No server specified or channel is invalid.").ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "send")
|
cgb.CreateCommand(Prefix + "send")
|
||||||
.Description("Send a message to someone on a different server through the bot. **Bot Owner Only!**\n**Usage**: .send Message text multi word!")
|
.Description("Send a message to someone on a different server through the bot. **Bot Owner Only!**\n**Usage**: `.send serverid|u:user_id Send this to a user!` or `.send serverid|c:channel_id Send this to a channel!`")
|
||||||
|
.Parameter("ids", ParameterType.Required)
|
||||||
.Parameter("msg", ParameterType.Unparsed)
|
.Parameter("msg", ParameterType.Unparsed)
|
||||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||||
.Do(async e =>
|
.Do(async e =>
|
||||||
{
|
{
|
||||||
if (commsUser != null)
|
var msg = e.GetArg("msg")?.Trim();
|
||||||
await commsUser.SendMessage(e.GetArg("msg")).ConfigureAwait(false);
|
|
||||||
else if (commsChannel != null)
|
if (string.IsNullOrWhiteSpace(msg))
|
||||||
await commsChannel.SendMessage(e.GetArg("msg")).ConfigureAwait(false);
|
return;
|
||||||
|
|
||||||
|
var ids = e.GetArg("ids").Split('-');
|
||||||
|
if (ids.Length != 2)
|
||||||
|
return;
|
||||||
|
var sid = ulong.Parse(ids[0]);
|
||||||
|
var server = NadekoBot.Client.Servers.Where(s => s.Id == sid).FirstOrDefault();
|
||||||
|
|
||||||
|
if (server == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ids[1].ToUpperInvariant().StartsWith("C:"))
|
||||||
|
{
|
||||||
|
var cid = ulong.Parse(ids[1].Substring(2));
|
||||||
|
var channel = server.TextChannels.Where(c => c.Id == cid).FirstOrDefault();
|
||||||
|
if (channel == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await channel.SendMessage(msg);
|
||||||
|
}
|
||||||
|
else if (ids[1].ToUpperInvariant().StartsWith("U:"))
|
||||||
|
{
|
||||||
|
var uid = ulong.Parse(ids[1].Substring(2));
|
||||||
|
var user = server.Users.Where(u => u.Id == uid).FirstOrDefault();
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await user.SendMessage(msg);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
await e.Channel.SendMessage("Failed. Make sure you've specified server and [channel or user]").ConfigureAwait(false);
|
{
|
||||||
|
await e.Channel.SendMessage("`Invalid format.`");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "mentionrole")
|
cgb.CreateCommand(Prefix + "mentionrole")
|
||||||
@ -874,37 +828,6 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "inrole")
|
|
||||||
.Description("Lists every person from the provided role or roles (separated by a ',') on this server.")
|
|
||||||
.Parameter("roles", ParameterType.Unparsed)
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
await Task.Run(async () =>
|
|
||||||
{
|
|
||||||
if (!e.User.ServerPermissions.MentionEveryone) return;
|
|
||||||
var arg = e.GetArg("roles").Split(',').Select(r => r.Trim());
|
|
||||||
string send = $"`Here is a list of users in a specfic role:`";
|
|
||||||
foreach (var roleStr in arg.Where(str => !string.IsNullOrWhiteSpace(str)))
|
|
||||||
{
|
|
||||||
var role = e.Server.FindRoles(roleStr).FirstOrDefault();
|
|
||||||
if (role == null) continue;
|
|
||||||
send += $"\n`{role.Name}`\n";
|
|
||||||
send += string.Join(", ", role.Members.Select(r => "**" + r.Name + "**#" + r.Discriminator));
|
|
||||||
}
|
|
||||||
|
|
||||||
while (send.Length > 2000)
|
|
||||||
{
|
|
||||||
var curstr = send.Substring(0, 2000);
|
|
||||||
await
|
|
||||||
e.Channel.Send(curstr.Substring(0,
|
|
||||||
curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1)).ConfigureAwait(false);
|
|
||||||
send = curstr.Substring(curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1) +
|
|
||||||
send.Substring(2000);
|
|
||||||
}
|
|
||||||
await e.Channel.Send(send).ConfigureAwait(false);
|
|
||||||
}).ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "unstuck")
|
cgb.CreateCommand(Prefix + "unstuck")
|
||||||
.Description("Clears the message queue. **Bot Owner Only!**")
|
.Description("Clears the message queue. **Bot Owner Only!**")
|
||||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||||
@ -967,27 +890,6 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await e.Channel.SendMessage(":ok:").ConfigureAwait(false);
|
await e.Channel.SendMessage(":ok:").ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "whoplays")
|
|
||||||
.Description("Shows a list of users who are playing the specified game.")
|
|
||||||
.Parameter("game", ParameterType.Unparsed)
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
var game = e.GetArg("game")?.Trim().ToUpperInvariant();
|
|
||||||
if (string.IsNullOrWhiteSpace(game))
|
|
||||||
return;
|
|
||||||
var en = e.Server.Users
|
|
||||||
.Where(u => u.CurrentGame?.Name?.ToUpperInvariant() == game)
|
|
||||||
.Select(u => u.Name);
|
|
||||||
|
|
||||||
var arr = en as string[] ?? en.ToArray();
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
if (arr.Length == 0)
|
|
||||||
await e.Channel.SendMessage("Nobody. (not 100% sure)").ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await e.Channel.SendMessage("```xl\n" + string.Join("\n", arr.GroupBy(item => (i++) / 3).Select(ig => string.Join("", ig.Select(el => $"• {el,-35}")))) + "\n```").ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "leave")
|
cgb.CreateCommand(Prefix + "leave")
|
||||||
.Description("Leaves a server with a supplied ID.\n**Usage**: `.leave 493243292839`")
|
.Description("Leaves a server with a supplied ID.\n**Usage**: `.leave 493243292839`")
|
||||||
.Parameter("num", ParameterType.Required)
|
.Parameter("num", ParameterType.Required)
|
||||||
@ -1003,6 +905,33 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await e.Channel.SendMessage("`Done.`").ConfigureAwait(false);
|
await e.Channel.SendMessage("`Done.`").ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "savechat")
|
||||||
|
.Description("Saves a number of messages to a text file and sends it to you. **Bot Owner Only** | `.chatsave 150`")
|
||||||
|
.Parameter("cnt", ParameterType.Required)
|
||||||
|
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var cntstr = e.GetArg("cnt")?.Trim();
|
||||||
|
int cnt;
|
||||||
|
if (!int.TryParse(cntstr, out cnt))
|
||||||
|
return;
|
||||||
|
ulong? lastmsgId = null;
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var msgs = new List<Message>(cnt);
|
||||||
|
while (cnt > 0)
|
||||||
|
{
|
||||||
|
var dlcnt = cnt < 100 ? cnt : 100;
|
||||||
|
|
||||||
|
var dledMsgs = await e.Channel.DownloadMessages(dlcnt, lastmsgId);
|
||||||
|
if (!dledMsgs.Any())
|
||||||
|
break;
|
||||||
|
msgs.AddRange(dledMsgs);
|
||||||
|
lastmsgId = msgs[msgs.Count - 1].Id;
|
||||||
|
cnt -= 100;
|
||||||
|
}
|
||||||
|
await e.User.SendFile($"Chatlog-{e.Server.Name}/#{e.Channel.Name}-{DateTime.Now}.txt", JsonConvert.SerializeObject(new { Messages = msgs.Select(s => s.ToString()) }, Formatting.Indented).ToStream());
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Classes;
|
using NadekoBot.Classes;
|
||||||
using NadekoBot.Modules.Permissions.Classes;
|
using NadekoBot.Modules.Permissions.Classes;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -45,14 +46,88 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
|
|
||||||
cgb.CreateCommand(Prefix + "listcustreact")
|
cgb.CreateCommand(Prefix + "listcustreact")
|
||||||
.Alias(Prefix + "lcr")
|
.Alias(Prefix + "lcr")
|
||||||
.Description($"Lists all current custom reactions (paginated with 5 commands per page).\n**Usage**:{Prefix}lcr 1")
|
.Description($"Lists all current custom reactions (paginated with 30 commands per page).\n**Usage**:{Prefix}lcr 1")
|
||||||
.Parameter("num", ParameterType.Required)
|
.Parameter("num", ParameterType.Required)
|
||||||
.Do(async e =>
|
.Do(async e =>
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
if (!int.TryParse(e.GetArg("num"), out num) || num <= 0) return;
|
if (!int.TryParse(e.GetArg("num"), out num) || num <= 0) num = 1;
|
||||||
string result = GetCustomsOnPage(num - 1); //People prefer starting with 1
|
var cmds = GetCustomsOnPage(num - 1);
|
||||||
await e.Channel.SendMessage(result).ConfigureAwait(false);
|
if (!cmds.Any())
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string result = SearchHelper.ShowInPrettyCode<string>(cmds, s => $"{s,-25}"); //People prefer starting with 1
|
||||||
|
await e.Channel.SendMessage($"`Showing page {num}:`\n" + result).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "showcustreact")
|
||||||
|
.Alias(Prefix + "scr")
|
||||||
|
.Description($"Shows all possible responses from a single custom reaction.\n**Usage**:{Prefix}scr %mention% bb")
|
||||||
|
.Parameter("name", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var name = e.GetArg("name")?.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
return;
|
||||||
|
if (!NadekoBot.Config.CustomReactions.ContainsKey(name))
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("`Can't find that custom reaction.`").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var items = NadekoBot.Config.CustomReactions[name];
|
||||||
|
var message = new StringBuilder($"Responses for {Format.Bold(name)}:\n");
|
||||||
|
var last = items.Last();
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
foreach (var reaction in items)
|
||||||
|
{
|
||||||
|
message.AppendLine($"[{i++}] " + Format.Code(reaction));
|
||||||
|
}
|
||||||
|
await e.Channel.SendMessage(message.ToString());
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "editcustreact")
|
||||||
|
.Alias(Prefix + "ecr")
|
||||||
|
.Description("Edits a custom reaction, arguments are custom reactions name, index to change, and a (multiword) message **Bot Owner Only** | `.ecr \"%mention% disguise\" 2 Test 123`")
|
||||||
|
.Parameter("name", ParameterType.Required)
|
||||||
|
.Parameter("index", ParameterType.Required)
|
||||||
|
.Parameter("message", ParameterType.Unparsed)
|
||||||
|
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var name = e.GetArg("name")?.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
return;
|
||||||
|
var indexstr = e.GetArg("index")?.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(indexstr))
|
||||||
|
return;
|
||||||
|
var msg = e.GetArg("message")?.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(msg))
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!NadekoBot.Config.CustomReactions.ContainsKey(name))
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("`Could not find given commandname`").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index;
|
||||||
|
if (!int.TryParse(indexstr, out index) || index < 1 || index > NadekoBot.Config.CustomReactions[name].Count)
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("`Invalid index.`").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
index = index - 1;
|
||||||
|
NadekoBot.Config.CustomReactions[name][index] = msg;
|
||||||
|
|
||||||
|
await Task.Run(() => Classes.JSONModels.ConfigHandler.SaveConfig()).ConfigureAwait(false);
|
||||||
|
await e.Channel.SendMessage($"Edited response #{index + 1} from `{name}`").ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "delcustreact")
|
cgb.CreateCommand(Prefix + "delcustreact")
|
||||||
@ -99,15 +174,17 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly int ItemsPerPage = 5;
|
private readonly int ItemsPerPage = 30;
|
||||||
|
|
||||||
private string GetCustomsOnPage(int page)
|
private IEnumerable<string> GetCustomsOnPage(int page)
|
||||||
{
|
{
|
||||||
var items = NadekoBot.Config.CustomReactions.Skip(page * ItemsPerPage).Take(ItemsPerPage);
|
var items = NadekoBot.Config.CustomReactions.Skip(page * ItemsPerPage).Take(ItemsPerPage);
|
||||||
if (!items.Any())
|
if (!items.Any())
|
||||||
{
|
{
|
||||||
return $"No items on page {page + 1}.";
|
return Enumerable.Empty<string>();
|
||||||
}
|
}
|
||||||
|
return items.Select(kvp => kvp.Key);
|
||||||
|
/*
|
||||||
var message = new StringBuilder($"--- Custom reactions - page {page + 1} ---\n");
|
var message = new StringBuilder($"--- Custom reactions - page {page + 1} ---\n");
|
||||||
foreach (var cr in items)
|
foreach (var cr in items)
|
||||||
{
|
{
|
||||||
@ -123,6 +200,7 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return message.ToString() + "\n";
|
return message.ToString() + "\n";
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Classes;
|
||||||
|
using NadekoBot.DataModels;
|
||||||
|
using NadekoBot.Modules.Permissions.Classes;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Administration.Commands
|
||||||
|
{
|
||||||
|
internal class IncidentsCommands : DiscordCommand
|
||||||
|
{
|
||||||
|
public IncidentsCommands(DiscordModule module) : base(module) { }
|
||||||
|
internal override void Init(CommandGroupBuilder cgb)
|
||||||
|
{
|
||||||
|
cgb.CreateCommand(Module.Prefix + "listincidents")
|
||||||
|
.Alias(Prefix + "lin")
|
||||||
|
.Description("List all UNREAD incidents and flags them as read.")
|
||||||
|
.AddCheck(SimpleCheckers.ManageServer())
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var sid = (long)e.Server.Id;
|
||||||
|
var incs = DbHandler.Instance.FindAll<Incident>(i => i.ServerId == sid && i.Read == false);
|
||||||
|
DbHandler.Instance.UpdateAll<Incident>(incs.Select(i => { i.Read = true; return i; }));
|
||||||
|
|
||||||
|
await e.User.SendMessage(string.Join("\n----------------------", incs.Select(i => i.Text)));
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Module.Prefix + "listallincidents")
|
||||||
|
.Alias(Prefix + "lain")
|
||||||
|
.Description("Sends you a file containing all incidents and flags them as read.")
|
||||||
|
.AddCheck(SimpleCheckers.ManageServer())
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var sid = (long)e.Server.Id;
|
||||||
|
var incs = DbHandler.Instance.FindAll<Incident>(i => i.ServerId == sid);
|
||||||
|
DbHandler.Instance.UpdateAll<Incident>(incs.Select(i => { i.Read = true; return i; }));
|
||||||
|
var data = string.Join("\n----------------------\n", incs.Select(i => i.Text));
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
var sw = new StreamWriter(ms);
|
||||||
|
sw.WriteLine(data);
|
||||||
|
sw.Flush();
|
||||||
|
sw.BaseStream.Position = 0;
|
||||||
|
await e.User.SendFile("incidents.txt", sw.BaseStream);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,19 +4,12 @@ using NadekoBot.Classes;
|
|||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Permissions.Classes;
|
using NadekoBot.Modules.Permissions.Classes;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration.Commands
|
namespace NadekoBot.Modules.Administration.Commands
|
||||||
{
|
{
|
||||||
internal class LogCommand : DiscordCommand
|
internal class LogCommand : DiscordCommand
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<Server, Channel> logs = new ConcurrentDictionary<Server, Channel>();
|
|
||||||
private readonly ConcurrentDictionary<Server, Channel> loggingPresences = new ConcurrentDictionary<Server, Channel>();
|
|
||||||
private readonly ConcurrentDictionary<Channel, Channel> voiceChannelLog = new ConcurrentDictionary<Channel, Channel>();
|
|
||||||
|
|
||||||
private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】";
|
private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】";
|
||||||
|
|
||||||
public LogCommand(DiscordModule module) : base(module)
|
public LogCommand(DiscordModule module) : base(module)
|
||||||
@ -58,8 +51,11 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch))
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
if (e.Before.Name != e.After.Name)
|
if (e.Before.Name != e.After.Name)
|
||||||
await ch.SendMessage($@"`{prettyCurrentTime}` **Channel Name Changed** `#{e.Before.Name}` (*{e.After.Id}*)
|
await ch.SendMessage($@"`{prettyCurrentTime}` **Channel Name Changed** `#{e.Before.Name}` (*{e.After.Id}*)
|
||||||
@ -76,8 +72,11 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch))
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
await ch.SendMessage($"❗`{prettyCurrentTime}`❗`Channel Deleted:` #{e.Channel.Name} (*{e.Channel.Id}*)").ConfigureAwait(false);
|
await ch.SendMessage($"❗`{prettyCurrentTime}`❗`Channel Deleted:` #{e.Channel.Name} (*{e.Channel.Id}*)").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -88,8 +87,11 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch))
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
await ch.SendMessage($"`{prettyCurrentTime}`🆕`Channel Created:` #{e.Channel.Mention} (*{e.Channel.Id}*)").ConfigureAwait(false);
|
await ch.SendMessage($"`{prettyCurrentTime}`🆕`Channel Created:` #{e.Channel.Mention} (*{e.Channel.Id}*)").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -100,8 +102,11 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch))
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
await ch.SendMessage($"`{prettyCurrentTime}`♻`User was unbanned:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
|
await ch.SendMessage($"`{prettyCurrentTime}`♻`User was unbanned:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -112,8 +117,11 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch))
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
await ch.SendMessage($"`{prettyCurrentTime}`✅`User joined:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
|
await ch.SendMessage($"`{prettyCurrentTime}`✅`User joined:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -124,8 +132,11 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch))
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
await ch.SendMessage($"`{prettyCurrentTime}`❗`User left:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
|
await ch.SendMessage($"`{prettyCurrentTime}`❗`User left:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -136,35 +147,28 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch))
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
await ch.SendMessage($"❗`{prettyCurrentTime}`❌`User banned:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
|
await ch.SendMessage($"❗`{prettyCurrentTime}`❌`User banned:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Func<CommandEventArgs, Task> DoFunc() => async e =>
|
|
||||||
{
|
|
||||||
Channel ch;
|
|
||||||
if (!logs.TryRemove(e.Server, out ch))
|
|
||||||
{
|
|
||||||
logs.TryAdd(e.Server, e.Channel);
|
|
||||||
await e.Channel.SendMessage($"❗**I WILL BEGIN LOGGING SERVER ACTIVITY IN THIS CHANNEL**❗").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await e.Channel.SendMessage($"❗**NO LONGER LOGGING IN {ch.Mention} CHANNEL**❗").ConfigureAwait(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
private async void MsgRecivd(object sender, MessageEventArgs e)
|
private async void MsgRecivd(object sender, MessageEventArgs e)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (e.Server == null || e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
|
if (e.Server == null || e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
|
||||||
return;
|
return;
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null || e.Channel.Id == chId)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch) || e.Channel == ch)
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
if (!string.IsNullOrWhiteSpace(e.Message.Text))
|
if (!string.IsNullOrWhiteSpace(e.Message.Text))
|
||||||
{
|
{
|
||||||
@ -188,8 +192,11 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
{
|
{
|
||||||
if (e.Server == null || e.Channel.IsPrivate || e.User?.Id == NadekoBot.Client.CurrentUser.Id)
|
if (e.Server == null || e.Channel.IsPrivate || e.User?.Id == NadekoBot.Client.CurrentUser.Id)
|
||||||
return;
|
return;
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null || e.Channel.Id == chId)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch) || e.Channel == ch)
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
if (!string.IsNullOrWhiteSpace(e.Message.Text))
|
if (!string.IsNullOrWhiteSpace(e.Message.Text))
|
||||||
{
|
{
|
||||||
@ -212,8 +219,11 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
{
|
{
|
||||||
if (e.Server == null || e.Channel.IsPrivate || e.User?.Id == NadekoBot.Client.CurrentUser.Id)
|
if (e.Server == null || e.Channel.IsPrivate || e.User?.Id == NadekoBot.Client.CurrentUser.Id)
|
||||||
return;
|
return;
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null || e.Channel.Id == chId)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch) || e.Channel == ch)
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
await ch.SendMessage(
|
await ch.SendMessage(
|
||||||
$@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
|
$@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
|
||||||
@ -225,19 +235,28 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
|
|||||||
}
|
}
|
||||||
private async void UsrUpdtd(object sender, UserUpdatedEventArgs e)
|
private async void UsrUpdtd(object sender, UserUpdatedEventArgs e)
|
||||||
{
|
{
|
||||||
|
var config = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
var chId = config.LogServerChannel;
|
||||||
|
if (chId != null)
|
||||||
{
|
{
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (loggingPresences.TryGetValue(e.Server, out ch))
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) != null)
|
||||||
|
{
|
||||||
if (e.Before.Status != e.After.Status)
|
if (e.Before.Status != e.After.Status)
|
||||||
{
|
{
|
||||||
await ch.SendMessage($"`{prettyCurrentTime}`**{e.Before.Name}** is now **{e.After.Status}**.").ConfigureAwait(false);
|
await ch.SendMessage($"`{prettyCurrentTime}`**{e.Before.Name}** is now **{e.After.Status}**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
ulong notifyChBeforeId;
|
||||||
|
ulong notifyChAfterId;
|
||||||
Channel notifyChBefore = null;
|
Channel notifyChBefore = null;
|
||||||
Channel notifyChAfter = null;
|
Channel notifyChAfter = null;
|
||||||
var beforeVch = e.Before.VoiceChannel;
|
var beforeVch = e.Before.VoiceChannel;
|
||||||
@ -246,11 +265,11 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
|
|||||||
var notifyJoin = false;
|
var notifyJoin = false;
|
||||||
if ((beforeVch != null || afterVch != null) && (beforeVch != afterVch)) // this means we need to notify for sure.
|
if ((beforeVch != null || afterVch != null) && (beforeVch != afterVch)) // this means we need to notify for sure.
|
||||||
{
|
{
|
||||||
if (beforeVch != null && voiceChannelLog.TryGetValue(beforeVch, out notifyChBefore))
|
if (beforeVch != null && config.VoiceChannelLog.TryGetValue(beforeVch.Id, out notifyChBeforeId) && (notifyChBefore = e.Before.Server.TextChannels.FirstOrDefault(tc => tc.Id == notifyChBeforeId)) != null)
|
||||||
{
|
{
|
||||||
notifyLeave = true;
|
notifyLeave = true;
|
||||||
}
|
}
|
||||||
if (afterVch != null && voiceChannelLog.TryGetValue(afterVch, out notifyChAfter))
|
if (afterVch != null && config.VoiceChannelLog.TryGetValue(afterVch.Id, out notifyChAfterId) && (notifyChAfter = e.After.Server.TextChannels.FirstOrDefault(tc => tc.Id == notifyChAfterId)) != null)
|
||||||
{
|
{
|
||||||
notifyJoin = true;
|
notifyJoin = true;
|
||||||
}
|
}
|
||||||
@ -272,8 +291,11 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null)
|
||||||
|
return;
|
||||||
Channel ch;
|
Channel ch;
|
||||||
if (!logs.TryGetValue(e.Server, out ch))
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
return;
|
return;
|
||||||
string str = $"🕔`{prettyCurrentTime}`";
|
string str = $"🕔`{prettyCurrentTime}`";
|
||||||
if (e.Before.Name != e.After.Name)
|
if (e.Before.Name != e.After.Name)
|
||||||
@ -331,21 +353,34 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
|
|||||||
.Description("Toggles logging in this channel. Logs every message sent/deleted/edited on the server. **Bot Owner Only!**")
|
.Description("Toggles logging in this channel. Logs every message sent/deleted/edited on the server. **Bot Owner Only!**")
|
||||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||||
.AddCheck(SimpleCheckers.ManageServer())
|
.AddCheck(SimpleCheckers.ManageServer())
|
||||||
.Do(DoFunc());
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
|
if (chId == null)
|
||||||
|
{
|
||||||
|
SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel = e.Channel.Id;
|
||||||
|
await e.Channel.SendMessage($"❗**I WILL BEGIN LOGGING SERVER ACTIVITY IN THIS CHANNEL**❗").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Channel ch;
|
||||||
|
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
|
||||||
|
return;
|
||||||
|
await e.Channel.SendMessage($"❗**NO LONGER LOGGING IN {ch.Mention} CHANNEL**❗").ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Module.Prefix + "userpresence")
|
cgb.CreateCommand(Module.Prefix + "userpresence")
|
||||||
.Description("Starts logging to this channel when someone from the server goes online/offline/idle.")
|
.Description("Starts logging to this channel when someone from the server goes online/offline/idle.")
|
||||||
.AddCheck(SimpleCheckers.ManageServer())
|
.AddCheck(SimpleCheckers.ManageServer())
|
||||||
.Do(async e =>
|
.Do(async e =>
|
||||||
{
|
{
|
||||||
Channel ch;
|
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
|
||||||
if (!loggingPresences.TryRemove(e.Server, out ch))
|
if (chId == null)
|
||||||
{
|
{
|
||||||
loggingPresences.TryAdd(e.Server, e.Channel);
|
SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel = e.Channel.Id;
|
||||||
await e.Channel.SendMessage($"**User presence notifications enabled.**").ConfigureAwait(false);
|
await e.Channel.SendMessage($"**User presence notifications enabled.**").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel = null;
|
||||||
await e.Channel.SendMessage($"**User presence notifications disabled.**").ConfigureAwait(false);
|
await e.Channel.SendMessage($"**User presence notifications disabled.**").ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -356,11 +391,12 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
|
|||||||
.Do(async e =>
|
.Do(async e =>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
var config = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||||
if (e.GetArg("all")?.ToLower() == "all")
|
if (e.GetArg("all")?.ToLower() == "all")
|
||||||
{
|
{
|
||||||
foreach (var voiceChannel in e.Server.VoiceChannels)
|
foreach (var voiceChannel in e.Server.VoiceChannels)
|
||||||
{
|
{
|
||||||
voiceChannelLog.TryAdd(voiceChannel, e.Channel);
|
config.VoiceChannelLog.TryAdd(voiceChannel.Id, e.Channel.Id);
|
||||||
}
|
}
|
||||||
await e.Channel.SendMessage("Started logging user presence for **ALL** voice channels!").ConfigureAwait(false);
|
await e.Channel.SendMessage("Started logging user presence for **ALL** voice channels!").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
@ -371,10 +407,10 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
|
|||||||
await e.Channel.SendMessage("💢 You are not in a voice channel right now. If you are, please rejoin it.").ConfigureAwait(false);
|
await e.Channel.SendMessage("💢 You are not in a voice channel right now. If you are, please rejoin it.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Channel throwaway;
|
ulong throwaway;
|
||||||
if (!voiceChannelLog.TryRemove(e.User.VoiceChannel, out throwaway))
|
if (!config.VoiceChannelLog.TryRemove(e.User.VoiceChannel.Id, out throwaway))
|
||||||
{
|
{
|
||||||
voiceChannelLog.TryAdd(e.User.VoiceChannel, e.Channel);
|
config.VoiceChannelLog.TryAdd(e.User.VoiceChannel.Id, e.Channel.Id);
|
||||||
await e.Channel.SendMessage($"`Logging user updates for` {e.User.VoiceChannel.Mention} `voice channel.`").ConfigureAwait(false);
|
await e.Channel.SendMessage($"`Logging user updates for` {e.User.VoiceChannel.Mention} `voice channel.`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -51,11 +51,9 @@ namespace NadekoBot.Modules.Administration.Commands
|
|||||||
{
|
{
|
||||||
if (PlayingPlaceholders.Count == 0
|
if (PlayingPlaceholders.Count == 0
|
||||||
|| NadekoBot.Config.RotatingStatuses.Count == 0
|
|| NadekoBot.Config.RotatingStatuses.Count == 0
|
||||||
|| i >= PlayingPlaceholders.Count
|
|
||||||
|| i >= NadekoBot.Config.RotatingStatuses.Count)
|
|| i >= NadekoBot.Config.RotatingStatuses.Count)
|
||||||
{
|
{
|
||||||
i = -1;
|
i = 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
status = NadekoBot.Config.RotatingStatuses[i];
|
status = NadekoBot.Config.RotatingStatuses[i];
|
||||||
status = PlayingPlaceholders.Aggregate(status,
|
status = PlayingPlaceholders.Aggregate(status,
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
using Discord.Commands;
|
|
||||||
using NadekoBot.Modules;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NadekoBot.Classes.Conversations.Commands
|
|
||||||
{
|
|
||||||
internal class CopyCommand : DiscordCommand
|
|
||||||
{
|
|
||||||
private readonly HashSet<ulong> CopiedUsers = new HashSet<ulong>();
|
|
||||||
|
|
||||||
public CopyCommand(DiscordModule module) : base(module)
|
|
||||||
{
|
|
||||||
NadekoBot.Client.MessageReceived += Client_MessageReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async void Client_MessageReceived(object sender, Discord.MessageEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(e.Message.Text))
|
|
||||||
return;
|
|
||||||
if (CopiedUsers.Contains(e.User.Id))
|
|
||||||
{
|
|
||||||
await e.Channel.SendMessage(e.Message.Text).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Func<CommandEventArgs, Task> DoFunc() => async e =>
|
|
||||||
{
|
|
||||||
if (CopiedUsers.Contains(e.User.Id)) return;
|
|
||||||
|
|
||||||
CopiedUsers.Add(e.User.Id);
|
|
||||||
await e.Channel.SendMessage(" I'll start copying you now.").ConfigureAwait(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
internal override void Init(CommandGroupBuilder cgb)
|
|
||||||
{
|
|
||||||
cgb.CreateCommand("copyme")
|
|
||||||
.Alias("cm")
|
|
||||||
.Description("Nadeko starts copying everything you say. Disable with cs")
|
|
||||||
.Do(DoFunc());
|
|
||||||
|
|
||||||
cgb.CreateCommand("cs")
|
|
||||||
.Alias("copystop")
|
|
||||||
.Description("Nadeko stops copying you")
|
|
||||||
.Do(StopCopy());
|
|
||||||
}
|
|
||||||
|
|
||||||
private Func<CommandEventArgs, Task> StopCopy() => async e =>
|
|
||||||
{
|
|
||||||
if (!CopiedUsers.Contains(e.User.Id)) return;
|
|
||||||
|
|
||||||
CopiedUsers.Remove(e.User.Id);
|
|
||||||
await e.Channel.SendMessage(" I wont copy anymore.").ConfigureAwait(false);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.Modules;
|
using Discord.Modules;
|
||||||
using NadekoBot.Classes.Conversations.Commands;
|
|
||||||
using NadekoBot.DataModels;
|
using NadekoBot.DataModels;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Conversations.Commands;
|
using NadekoBot.Modules.Conversations.Commands;
|
||||||
@ -19,7 +18,6 @@ namespace NadekoBot.Modules.Conversations
|
|||||||
private const string firestr = "🔥 ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้ 🔥";
|
private const string firestr = "🔥 ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้ 🔥";
|
||||||
public Conversations()
|
public Conversations()
|
||||||
{
|
{
|
||||||
commands.Add(new CopyCommand(this));
|
|
||||||
commands.Add(new RipCommand(this));
|
commands.Add(new RipCommand(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,21 +253,6 @@ namespace NadekoBot.Modules.Conversations
|
|||||||
await e.Channel.SendMessage(construct).ConfigureAwait(false);
|
await e.Channel.SendMessage(construct).ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand("av")
|
|
||||||
.Alias("avatar")
|
|
||||||
.Parameter("mention", ParameterType.Required)
|
|
||||||
.Description("Shows a mentioned person's avatar.\n**Usage**: ~av @X")
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
var usr = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault();
|
|
||||||
if (usr == null)
|
|
||||||
{
|
|
||||||
await e.Channel.SendMessage("Invalid user specified.").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await e.Channel.SendMessage(await usr.AvatarUrl.ShortenUrl()).ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,11 @@ namespace NadekoBot.Classes
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected DiscordModule Module { get; }
|
protected DiscordModule Module { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parent module's prefix
|
||||||
|
/// </summary>
|
||||||
|
protected string Prefix => Module.Prefix;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of discord command,
|
/// Creates a new instance of discord command,
|
||||||
/// use ": base(module)" in the derived class'
|
/// use ": base(module)" in the derived class'
|
||||||
|
@ -79,7 +79,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
await e.Channel.SendFile(images.Count + " cards.jpg", bitmap.ToStream()).ConfigureAwait(false);
|
await e.Channel.SendFile(images.Count + " cards.jpg", bitmap.ToStream()).ConfigureAwait(false);
|
||||||
if (cardObjects.Count == 5)
|
if (cardObjects.Count == 5)
|
||||||
{
|
{
|
||||||
await e.Channel.SendMessage(Cards.GetHandValue(cardObjects)).ConfigureAwait(false);
|
await e.Channel.SendMessage($"{e.User.Mention} `{Cards.GetHandValue(cardObjects)}`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Classes;
|
using NadekoBot.Classes;
|
||||||
|
using NadekoBot.Modules.Permissions.Classes;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Games.Commands
|
namespace NadekoBot.Modules.Games.Commands
|
||||||
@ -18,11 +20,31 @@ namespace NadekoBot.Modules.Games.Commands
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class PlantPick : DiscordCommand
|
class PlantPick : DiscordCommand
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private Random rng;
|
||||||
public PlantPick(DiscordModule module) : base(module)
|
public PlantPick(DiscordModule module) : base(module)
|
||||||
{
|
{
|
||||||
|
NadekoBot.Client.MessageReceived += PotentialFlowerGeneration;
|
||||||
|
rng = new Random();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async void PotentialFlowerGeneration(object sender, Discord.MessageEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Server == null || e.Channel.IsPrivate)
|
||||||
|
return;
|
||||||
|
var config = Classes.SpecificConfigurations.Default.Of(e.Server.Id);
|
||||||
|
if (config.GenerateCurrencyChannels.Contains(e.Channel.Id))
|
||||||
|
{
|
||||||
|
var rnd = Math.Abs(GetRandomNumber());
|
||||||
|
if ((rnd % 50) == 0)
|
||||||
|
{
|
||||||
|
var msg = await e.Channel.SendFile(GetRandomCurrencyImagePath());
|
||||||
|
await e.Channel.SendMessage($"❗ A random {NadekoBot.Config.CurrencyName} appeared! Pick it up by typing `>pick`");
|
||||||
|
plantedFlowerChannels.AddOrUpdate(e.Channel.Id, msg, (u, m) => { m.Delete().GetAwaiter().GetResult(); return msg; });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
//channelid/messageid pair
|
//channelid/messageid pair
|
||||||
ConcurrentDictionary<ulong, Message> plantedFlowerChannels = new ConcurrentDictionary<ulong, Message>();
|
ConcurrentDictionary<ulong, Message> plantedFlowerChannels = new ConcurrentDictionary<ulong, Message>();
|
||||||
|
|
||||||
@ -65,8 +87,7 @@ namespace NadekoBot.Modules.Games.Commands
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rng = new Random();
|
var file = GetRandomCurrencyImagePath();
|
||||||
var file = Directory.GetFiles("data/currency_images").OrderBy(s => rng.Next()).FirstOrDefault();
|
|
||||||
Message msg;
|
Message msg;
|
||||||
//todo send message after, not in lock
|
//todo send message after, not in lock
|
||||||
if (file == null)
|
if (file == null)
|
||||||
@ -80,6 +101,38 @@ namespace NadekoBot.Modules.Games.Commands
|
|||||||
await Task.Delay(20000).ConfigureAwait(false);
|
await Task.Delay(20000).ConfigureAwait(false);
|
||||||
await msg2.Delete().ConfigureAwait(false);
|
await msg2.Delete().ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "gencurrency")
|
||||||
|
.Alias(Prefix + "gc")
|
||||||
|
.Description($"Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a {NadekoBot.Config.CurrencyName}. Requires Manage Messages permission. | `>gc`")
|
||||||
|
.AddCheck(SimpleCheckers.ManageMessages())
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var config = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||||
|
if (config.GenerateCurrencyChannels.Remove(e.Channel.Id))
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("`Currency generation disabled on this channel.`");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.GenerateCurrencyChannels.Add(e.Channel.Id);
|
||||||
|
await e.Channel.SendMessage("`Currency generation enabled on this channel.`");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetRandomCurrencyImagePath() =>
|
||||||
|
Directory.GetFiles("data/currency_images").OrderBy(s => rng.Next()).FirstOrDefault();
|
||||||
|
|
||||||
|
int GetRandomNumber()
|
||||||
|
{
|
||||||
|
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
|
||||||
|
{
|
||||||
|
byte[] rno = new byte[4];
|
||||||
|
rg.GetBytes(rno);
|
||||||
|
int randomvalue = BitConverter.ToInt32(rno, 0);
|
||||||
|
return randomvalue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ Version: `{NadekoStats.Instance.BotVersion}`";
|
|||||||
.Description("Sends a readme and a guide links to the channel.")
|
.Description("Sends a readme and a guide links to the channel.")
|
||||||
.Do(async e =>
|
.Do(async e =>
|
||||||
await e.Channel.SendMessage(
|
await e.Channel.SendMessage(
|
||||||
@"**FULL README**: <https://github.com/Kwoth/NadekoBot/blob/master/README.md>
|
@"**Wiki with all info**: <https://github.com/Kwoth/NadekoBot/wiki>
|
||||||
|
|
||||||
**WINDOWS SETUP GUIDE**: <https://github.com/Kwoth/NadekoBot/blob/master/ComprehensiveGuide.md>
|
**WINDOWS SETUP GUIDE**: <https://github.com/Kwoth/NadekoBot/blob/master/ComprehensiveGuide.md>
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.Modules;
|
using Discord.Modules;
|
||||||
|
using NadekoBot.Classes;
|
||||||
using NadekoBot.Classes.Help.Commands;
|
using NadekoBot.Classes.Help.Commands;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Permissions.Classes;
|
using NadekoBot.Modules.Permissions.Classes;
|
||||||
@ -54,10 +55,8 @@ namespace NadekoBot.Modules.Help
|
|||||||
}
|
}
|
||||||
var i = 0;
|
var i = 0;
|
||||||
if (module != "customreactions" && module != "conversations")
|
if (module != "customreactions" && module != "conversations")
|
||||||
await e.Channel.SendMessage("`List Of Commands:`\n```xl\n" +
|
await e.Channel.SendMessage("`List Of Commands:`\n" + SearchHelper.ShowInPrettyCode<Command>(cmdsArray,
|
||||||
string.Join("\n", cmdsArray.GroupBy(item => (i++) / 3)
|
el => $"{el.Text,-15}{"[" + el.Aliases.FirstOrDefault() + "]",-8}"))
|
||||||
.Select(ig => string.Join("", ig.Select(el => $"{el.Text,-15}" + $"{"[" + el.Aliases.FirstOrDefault() + "]",-8}"))))
|
|
||||||
+ $"\n```")
|
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await e.Channel.SendMessage("`List Of Commands:`\n• " + string.Join("\n• ", cmdsArray.Select(c => $"{c.Text}")));
|
await e.Channel.SendMessage("`List Of Commands:`\n• " + string.Join("\n• ", cmdsArray.Select(c => $"{c.Text}")));
|
||||||
|
@ -50,6 +50,7 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
private bool Destroyed { get; set; } = false;
|
private bool Destroyed { get; set; } = false;
|
||||||
public bool RepeatSong { get; private set; } = false;
|
public bool RepeatSong { get; private set; } = false;
|
||||||
public bool RepeatPlaylist { get; private set; } = false;
|
public bool RepeatPlaylist { get; private set; } = false;
|
||||||
|
public bool Autoplay { get; private set; } = false;
|
||||||
|
|
||||||
public MusicPlayer(Channel startingVoiceChannel, float? defaultVolume)
|
public MusicPlayer(Channel startingVoiceChannel, float? defaultVolume)
|
||||||
{
|
{
|
||||||
@ -173,6 +174,7 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
throw new ArgumentNullException(nameof(s));
|
throw new ArgumentNullException(nameof(s));
|
||||||
lock (playlistLock)
|
lock (playlistLock)
|
||||||
{
|
{
|
||||||
|
s.MusicPlayer = this;
|
||||||
playlist.Add(s);
|
playlist.Add(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,5 +241,7 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
internal bool ToggleRepeatSong() => this.RepeatSong = !this.RepeatSong;
|
internal bool ToggleRepeatSong() => this.RepeatSong = !this.RepeatSong;
|
||||||
|
|
||||||
internal bool ToggleRepeatPlaylist() => this.RepeatPlaylist = !this.RepeatPlaylist;
|
internal bool ToggleRepeatPlaylist() => this.RepeatPlaylist = !this.RepeatPlaylist;
|
||||||
|
|
||||||
|
internal bool ToggleAutoplay() => this.Autoplay = !this.Autoplay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Song(SongInfo songInfo)
|
public Song(SongInfo songInfo)
|
||||||
{
|
{
|
||||||
this.SongInfo = songInfo;
|
this.SongInfo = songInfo;
|
||||||
}
|
}
|
||||||
@ -67,6 +67,12 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Song SetMusicPlayer(MusicPlayer mp)
|
||||||
|
{
|
||||||
|
this.MusicPlayer = mp;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private Task BufferSong(CancellationToken cancelToken) =>
|
private Task BufferSong(CancellationToken cancelToken) =>
|
||||||
Task.Factory.StartNew(async () =>
|
Task.Factory.StartNew(async () =>
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using NadekoBot.Classes;
|
using NadekoBot.Classes;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -34,18 +35,22 @@ namespace NadekoBot.Modules.Music.Classes
|
|||||||
|
|
||||||
public class SoundCloudVideo
|
public class SoundCloudVideo
|
||||||
{
|
{
|
||||||
public string Kind = "";
|
public string Kind { get; set; } = "";
|
||||||
public long Id = 0;
|
public long Id { get; set; } = 0;
|
||||||
public SoundCloudUser User = new SoundCloudUser();
|
public SoundCloudUser User { get; set; } = new SoundCloudUser();
|
||||||
public string Title = "";
|
public string Title { get; set; } = "";
|
||||||
|
[JsonIgnore]
|
||||||
public string FullName => User.Name + " - " + Title;
|
public string FullName => User.Name + " - " + Title;
|
||||||
public bool Streamable = false;
|
public bool Streamable { get; set; } = false;
|
||||||
|
[JsonProperty("permalink_url")]
|
||||||
|
public string TrackLink { get; set; } = "";
|
||||||
|
[JsonIgnore]
|
||||||
public string StreamLink => $"https://api.soundcloud.com/tracks/{Id}/stream?client_id={NadekoBot.Creds.SoundCloudClientID}";
|
public string StreamLink => $"https://api.soundcloud.com/tracks/{Id}/stream?client_id={NadekoBot.Creds.SoundCloudClientID}";
|
||||||
}
|
}
|
||||||
public class SoundCloudUser
|
public class SoundCloudUser
|
||||||
{
|
{
|
||||||
[Newtonsoft.Json.JsonProperty("username")]
|
[Newtonsoft.Json.JsonProperty("username")]
|
||||||
public string Name;
|
public string Name { get; set; }
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
{"kind":"track",
|
{"kind":"track",
|
||||||
|
@ -6,6 +6,7 @@ using NadekoBot.DataModels;
|
|||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Music.Classes;
|
using NadekoBot.Modules.Music.Classes;
|
||||||
using NadekoBot.Modules.Permissions.Classes;
|
using NadekoBot.Modules.Permissions.Classes;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -19,7 +20,6 @@ namespace NadekoBot.Modules.Music
|
|||||||
{
|
{
|
||||||
|
|
||||||
public static ConcurrentDictionary<Server, MusicPlayer> MusicPlayers = new ConcurrentDictionary<Server, MusicPlayer>();
|
public static ConcurrentDictionary<Server, MusicPlayer> MusicPlayers = new ConcurrentDictionary<Server, MusicPlayer>();
|
||||||
public static ConcurrentDictionary<ulong, float> DefaultMusicVolumes = new ConcurrentDictionary<ulong, float>();
|
|
||||||
|
|
||||||
public MusicModule()
|
public MusicModule()
|
||||||
{
|
{
|
||||||
@ -53,30 +53,24 @@ namespace NadekoBot.Modules.Music
|
|||||||
cgb.CreateCommand("stop")
|
cgb.CreateCommand("stop")
|
||||||
.Alias("s")
|
.Alias("s")
|
||||||
.Description("Stops the music and clears the playlist. Stays in the channel.\n**Usage**: `!m s`")
|
.Description("Stops the music and clears the playlist. Stays in the channel.\n**Usage**: `!m s`")
|
||||||
.Do(async e =>
|
.Do(e =>
|
||||||
{
|
|
||||||
await Task.Run(() =>
|
|
||||||
{
|
{
|
||||||
MusicPlayer musicPlayer;
|
MusicPlayer musicPlayer;
|
||||||
if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) return;
|
if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) return;
|
||||||
if (e.User.VoiceChannel == musicPlayer.PlaybackVoiceChannel)
|
if (e.User.VoiceChannel == musicPlayer.PlaybackVoiceChannel)
|
||||||
musicPlayer.Stop();
|
musicPlayer.Stop();
|
||||||
}).ConfigureAwait(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand("destroy")
|
cgb.CreateCommand("destroy")
|
||||||
.Alias("d")
|
.Alias("d")
|
||||||
.Description("Completely stops the music and unbinds the bot from the channel. " +
|
.Description("Completely stops the music and unbinds the bot from the channel. " +
|
||||||
"(may cause weird behaviour)\n**Usage**: `!m d`")
|
"(may cause weird behaviour)\n**Usage**: `!m d`")
|
||||||
.Do(async e =>
|
.Do(e =>
|
||||||
{
|
|
||||||
await Task.Run(() =>
|
|
||||||
{
|
{
|
||||||
MusicPlayer musicPlayer;
|
MusicPlayer musicPlayer;
|
||||||
if (!MusicPlayers.TryRemove(e.Server, out musicPlayer)) return;
|
if (!MusicPlayers.TryRemove(e.Server, out musicPlayer)) return;
|
||||||
if (e.User.VoiceChannel == musicPlayer.PlaybackVoiceChannel)
|
if (e.User.VoiceChannel == musicPlayer.PlaybackVoiceChannel)
|
||||||
musicPlayer.Destroy();
|
musicPlayer.Destroy();
|
||||||
}).ConfigureAwait(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand("pause")
|
cgb.CreateCommand("pause")
|
||||||
@ -111,6 +105,21 @@ namespace NadekoBot.Modules.Music
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//cgb.CreateCommand("soundcloudqueue")
|
||||||
|
// .Alias("sq")
|
||||||
|
// .Description("Queue a soundcloud song using keywords. Bot will join your voice channel." +
|
||||||
|
// "**You must be in a voice channel**.\n**Usage**: `!m sq Dream Of Venice`")
|
||||||
|
// .Parameter("query", ParameterType.Unparsed)
|
||||||
|
// .Do(async e =>
|
||||||
|
// {
|
||||||
|
// await QueueSong(e.Channel, e.User.VoiceChannel, e.GetArg("query")).ConfigureAwait(false);
|
||||||
|
// if (e.Server.CurrentUser.GetPermissions(e.Channel).ManageMessages)
|
||||||
|
// {
|
||||||
|
// await Task.Delay(10000).ConfigureAwait(false);
|
||||||
|
// await e.Message.Delete().ConfigureAwait(false);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
cgb.CreateCommand("listqueue")
|
cgb.CreateCommand("listqueue")
|
||||||
.Alias("lq")
|
.Alias("lq")
|
||||||
.Description("Lists 15 currently queued songs per page. Default page is 1.\n**Usage**: `!m lq` or `!m lq 2`")
|
.Description("Lists 15 currently queued songs per page. Default page is 1.\n**Usage**: `!m lq` or `!m lq 2`")
|
||||||
@ -200,7 +209,8 @@ namespace NadekoBot.Modules.Music
|
|||||||
await e.Channel.SendMessage("Volume number invalid.").ConfigureAwait(false);
|
await e.Channel.SendMessage("Volume number invalid.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DefaultMusicVolumes.AddOrUpdate(e.Server.Id, volume / 100, (key, newval) => volume / 100);
|
var conf = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||||
|
conf.DefaultMusicVolume = volume / 100;
|
||||||
await e.Channel.SendMessage($"🎵 `Default volume set to {volume}%`").ConfigureAwait(false);
|
await e.Channel.SendMessage($"🎵 `Default volume set to {volume}%`").ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -302,6 +312,37 @@ namespace NadekoBot.Modules.Music
|
|||||||
await msg.Edit("🎵 `Playlist queue complete.`").ConfigureAwait(false);
|
await msg.Edit("🎵 `Playlist queue complete.`").ConfigureAwait(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand("soundcloudpl")
|
||||||
|
.Alias("scpl")
|
||||||
|
.Description("Queue a soundcloud playlist using a link. | `!m scpl https://soundcloud.com/saratology/sets/symphony`")
|
||||||
|
.Parameter("pl", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var pl = e.GetArg("pl")?.Trim();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(pl))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var scvids = JObject.Parse(await SearchHelper.GetResponseStringAsync($"http://api.soundcloud.com/resolve?url={pl}&client_id={NadekoBot.Creds.SoundCloudClientID}"))["tracks"].ToObject<SoundCloudVideo[]>();
|
||||||
|
await QueueSong(e.Channel, e.User.VoiceChannel, scvids[0].TrackLink);
|
||||||
|
|
||||||
|
MusicPlayer mp;
|
||||||
|
if (!MusicPlayers.TryGetValue(e.Server, out mp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var svideo in scvids.Skip(1))
|
||||||
|
{
|
||||||
|
mp.AddSong(new Song(new Classes.SongInfo
|
||||||
|
{
|
||||||
|
Title = svideo.FullName,
|
||||||
|
Provider = "SoundCloud",
|
||||||
|
Uri = svideo.StreamLink,
|
||||||
|
ProviderType = MusicType.Normal,
|
||||||
|
Query = svideo.TrackLink,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
cgb.CreateCommand("localplaylst")
|
cgb.CreateCommand("localplaylst")
|
||||||
.Alias("lopl")
|
.Alias("lopl")
|
||||||
.Description("Queues all songs from a directory. **Bot Owner Only!**\n**Usage**: `!m lopl C:/music/classical`")
|
.Description("Queues all songs from a directory. **Bot Owner Only!**\n**Usage**: `!m lopl C:/music/classical`")
|
||||||
@ -430,7 +471,8 @@ namespace NadekoBot.Modules.Music
|
|||||||
|
|
||||||
var s = playlist[n1 - 1];
|
var s = playlist[n1 - 1];
|
||||||
playlist.Insert(n2 - 1, s);
|
playlist.Insert(n2 - 1, s);
|
||||||
playlist.RemoveAt(n1 - 1);
|
var nn1 = n2 < n1 ? n1 : n1 - 1;
|
||||||
|
playlist.RemoveAt(nn1);
|
||||||
|
|
||||||
await e.Channel.SendMessage($"🎵`Moved` {s.PrettyName} `from #{n1} to #{n2}`");
|
await e.Channel.SendMessage($"🎵`Moved` {s.PrettyName} `from #{n1} to #{n2}`");
|
||||||
|
|
||||||
@ -609,6 +651,23 @@ namespace NadekoBot.Modules.Music
|
|||||||
e.Channel.SendMessage($"```js\n--- List of saved playlists ---\n\n" + string.Join("\n", result.Select(r => $"'{r.Name}-{r.Id}' by {r.Creator} ({r.SongCnt} songs)")) + $"\n\n --- Page {num} ---```");
|
e.Channel.SendMessage($"```js\n--- List of saved playlists ---\n\n" + string.Join("\n", result.Select(r => $"'{r.Name}-{r.Id}' by {r.Creator} ({r.SongCnt} songs)")) + $"\n\n --- Page {num} ---```");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand("deleteplaylist")
|
||||||
|
.Alias("delpls")
|
||||||
|
.Description("Deletes a saved playlist. Only if you made it or if you are the bot owner. | `!m delpls animu-5`")
|
||||||
|
.Parameter("pl", ParameterType.Required)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var pl = e.GetArg("pl").Trim().Split('-')[1];
|
||||||
|
if (string.IsNullOrWhiteSpace(pl))
|
||||||
|
return;
|
||||||
|
var plnum = int.Parse(pl);
|
||||||
|
if (NadekoBot.IsOwner(e.User.Id))
|
||||||
|
DbHandler.Instance.Delete<MusicPlaylist>(plnum);
|
||||||
|
else
|
||||||
|
DbHandler.Instance.DeleteWhere<MusicPlaylist>(mp => mp.Id == plnum && (long)e.User.Id == mp.CreatorId);
|
||||||
|
await e.Channel.SendMessage("`Ok.` :ok:");
|
||||||
|
});
|
||||||
|
|
||||||
cgb.CreateCommand("goto")
|
cgb.CreateCommand("goto")
|
||||||
.Description("Goes to a specific time in seconds in a song.")
|
.Description("Goes to a specific time in seconds in a song.")
|
||||||
.Parameter("time")
|
.Parameter("time")
|
||||||
@ -659,10 +718,26 @@ namespace NadekoBot.Modules.Music
|
|||||||
return;
|
return;
|
||||||
await e.Channel.SendMessage($"🎶`Current song:` <{curSong.SongInfo.Query}>");
|
await e.Channel.SendMessage($"🎶`Current song:` <{curSong.SongInfo.Query}>");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand("autoplay")
|
||||||
|
.Alias("ap")
|
||||||
|
.Description("Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty)")
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
|
||||||
|
MusicPlayer musicPlayer;
|
||||||
|
if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!musicPlayer.ToggleAutoplay())
|
||||||
|
await e.Channel.SendMessage("🎶`Autoplay disabled.`");
|
||||||
|
else
|
||||||
|
await e.Channel.SendMessage("🎶`Autoplay enabled.`");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task QueueSong(Channel textCh, Channel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal)
|
public static async Task QueueSong(Channel textCh, Channel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal)
|
||||||
{
|
{
|
||||||
if (voiceCh == null || voiceCh.Server != textCh.Server)
|
if (voiceCh == null || voiceCh.Server != textCh.Server)
|
||||||
{
|
{
|
||||||
@ -675,10 +750,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
|
|
||||||
var musicPlayer = MusicPlayers.GetOrAdd(textCh.Server, server =>
|
var musicPlayer = MusicPlayers.GetOrAdd(textCh.Server, server =>
|
||||||
{
|
{
|
||||||
float? vol = null;
|
float vol = SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume;
|
||||||
float throwAway;
|
|
||||||
if (DefaultMusicVolumes.TryGetValue(server.Id, out throwAway))
|
|
||||||
vol = throwAway;
|
|
||||||
var mp = new MusicPlayer(voiceCh, vol);
|
var mp = new MusicPlayer(voiceCh, vol);
|
||||||
|
|
||||||
|
|
||||||
@ -695,8 +767,15 @@ namespace NadekoBot.Modules.Music
|
|||||||
if (playingMessage != null)
|
if (playingMessage != null)
|
||||||
await playingMessage.Delete().ConfigureAwait(false);
|
await playingMessage.Delete().ConfigureAwait(false);
|
||||||
lastFinishedMessage = await textCh.SendMessage($"🎵`Finished`{song.PrettyName}").ConfigureAwait(false);
|
lastFinishedMessage = await textCh.SendMessage($"🎵`Finished`{song.PrettyName}").ConfigureAwait(false);
|
||||||
|
if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.Provider == "YouTube")
|
||||||
|
{
|
||||||
|
await QueueSong(textCh, voiceCh, await SearchHelper.GetRelatedVideoId(song.SongInfo.Query), silent, musicType).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
}
|
}
|
||||||
catch { }
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mp.OnStarted += async (s, song) =>
|
mp.OnStarted += async (s, song) =>
|
||||||
@ -719,8 +798,6 @@ namespace NadekoBot.Modules.Music
|
|||||||
return mp;
|
return mp;
|
||||||
});
|
});
|
||||||
var resolvedSong = await Song.ResolveSong(query, musicType).ConfigureAwait(false);
|
var resolvedSong = await Song.ResolveSong(query, musicType).ConfigureAwait(false);
|
||||||
resolvedSong.MusicPlayer = musicPlayer;
|
|
||||||
|
|
||||||
musicPlayer.AddSong(resolvedSong);
|
musicPlayer.AddSong(resolvedSong);
|
||||||
if (!silent)
|
if (!silent)
|
||||||
{
|
{
|
||||||
|
@ -25,9 +25,9 @@ namespace NadekoBot.Modules.Permissions.Commands
|
|||||||
if (filterRegex.IsMatch(args.Message.RawText))
|
if (filterRegex.IsMatch(args.Message.RawText))
|
||||||
{
|
{
|
||||||
await args.Message.Delete().ConfigureAwait(false);
|
await args.Message.Delete().ConfigureAwait(false);
|
||||||
IncidentsHandler.Add(args.Server.Id, $"User [{args.User.Name}/{args.User.Id}] posted " +
|
IncidentsHandler.Add(args.Server.Id, args.Channel.Id, $"User [{args.User.Name}/{args.User.Id}] posted " +
|
||||||
$"INVITE LINK in [{args.Channel.Name}/{args.Channel.Id}] channel. " +
|
$"INVITE LINK in [{args.Channel.Name}/{args.Channel.Id}] channel.\n" +
|
||||||
$"Full message: [[{args.Message.Text}]]");
|
$"`Full message:` {args.Message.Text}");
|
||||||
if (serverPerms.Verbose)
|
if (serverPerms.Verbose)
|
||||||
await args.Channel.SendMessage($"{args.User.Mention} Invite links are not " +
|
await args.Channel.SendMessage($"{args.User.Mention} Invite links are not " +
|
||||||
$"allowed on this channel.")
|
$"allowed on this channel.")
|
||||||
|
@ -23,9 +23,9 @@ namespace NadekoBot.Modules.Permissions.Commands
|
|||||||
if (serverPerms.Words.Any(w => wordsInMessage.Contains(w)))
|
if (serverPerms.Words.Any(w => wordsInMessage.Contains(w)))
|
||||||
{
|
{
|
||||||
await args.Message.Delete().ConfigureAwait(false);
|
await args.Message.Delete().ConfigureAwait(false);
|
||||||
IncidentsHandler.Add(args.Server.Id, $"User [{args.User.Name}/{args.User.Id}] posted " +
|
IncidentsHandler.Add(args.Server.Id, args.Channel.Id, $"User [{args.User.Name}/{args.User.Id}] posted " +
|
||||||
$"BANNED WORD in [{args.Channel.Name}/{args.Channel.Id}] channel. " +
|
$"BANNED WORD in [{args.Channel.Name}/{args.Channel.Id}] channel.\n" +
|
||||||
$"Full message: [[{args.Message.Text}]]");
|
$"`Full message:` {args.Message.Text}");
|
||||||
if (serverPerms.Verbose)
|
if (serverPerms.Verbose)
|
||||||
await args.Channel.SendMessage($"{args.User.Mention} One or more of the words you used " +
|
await args.Channel.SendMessage($"{args.User.Mention} One or more of the words you used " +
|
||||||
$"in that sentence are not allowed here.")
|
$"in that sentence are not allowed here.")
|
||||||
|
46
NadekoBot/Modules/Searches/Commands/MemegenCommands.cs
Normal file
46
NadekoBot/Modules/Searches/Commands/MemegenCommands.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Classes;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Searches.Commands
|
||||||
|
{
|
||||||
|
class MemegenCommands : DiscordCommand
|
||||||
|
{
|
||||||
|
public MemegenCommands(DiscordModule module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Init(CommandGroupBuilder cgb)
|
||||||
|
{
|
||||||
|
cgb.CreateCommand(Prefix + "memelist")
|
||||||
|
.Description("Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/")
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
await e.Channel.SendMessage("`List Of Commands:`\n```xl\n" +
|
||||||
|
string.Join("\n", JsonConvert.DeserializeObject<Dictionary<string, string>>(await SearchHelper.GetResponseStringAsync("http://memegen.link/templates/"))
|
||||||
|
.Select(kvp => Path.GetFileName(kvp.Value))
|
||||||
|
.GroupBy(item => (i++) / 4)
|
||||||
|
.Select(ig => string.Join("", ig.Select(el => $"{el,-17}"))))
|
||||||
|
+ $"\n```").ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "memegen")
|
||||||
|
.Description("Generates a meme from memelist with top and bottom text. | `~memegen biw \"gets iced coffee\" \"in the winter\"`")
|
||||||
|
.Parameter("meme", ParameterType.Required)
|
||||||
|
.Parameter("toptext", ParameterType.Required)
|
||||||
|
.Parameter("bottext", ParameterType.Required)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var meme = e.GetArg("meme");
|
||||||
|
var top = Uri.EscapeDataString(e.GetArg("toptext").Replace(' ', '-'));
|
||||||
|
var bot = Uri.EscapeDataString(e.GetArg("bottext").Replace(' ', '-'));
|
||||||
|
await e.Channel.SendMessage($"http://memegen.link/{meme}/{top}/{bot}.jpg");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
268
NadekoBot/Modules/Searches/Commands/OsuCommands.cs
Normal file
268
NadekoBot/Modules/Searches/Commands/OsuCommands.cs
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Classes;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Searches.Commands
|
||||||
|
{
|
||||||
|
internal class OsuCommands : DiscordCommand
|
||||||
|
{
|
||||||
|
public OsuCommands(DiscordModule module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Init(CommandGroupBuilder cgb)
|
||||||
|
{
|
||||||
|
cgb.CreateCommand(Module.Prefix + "osu")
|
||||||
|
.Description("Shows osu stats for a player.\n**Usage**: `~osu Name` or `~osu Name taiko`")
|
||||||
|
.Parameter("usr", ParameterType.Required)
|
||||||
|
.Parameter("mode", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(e.GetArg("usr")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
using (WebClient cl = new WebClient())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var m = 0;
|
||||||
|
if (!string.IsNullOrWhiteSpace(e.GetArg("mode")))
|
||||||
|
{
|
||||||
|
m = ResolveGameMode(e.GetArg("mode"));
|
||||||
|
}
|
||||||
|
|
||||||
|
cl.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
|
||||||
|
cl.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/5.0 (Windows NT 6.2; Win64; x64)");
|
||||||
|
cl.DownloadDataAsync(new Uri($"http://lemmmy.pw/osusig/sig.php?uname={ e.GetArg("usr") }&flagshadow&xpbar&xpbarhex&pp=2&mode={m}"));
|
||||||
|
cl.DownloadDataCompleted += async (s, cle) =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await e.Channel.SendFile($"{e.GetArg("usr")}.png", new MemoryStream(cle.Result)).ConfigureAwait(false);
|
||||||
|
await e.Channel.SendMessage($"`Profile Link:`https://osu.ppy.sh/u/{Uri.EscapeDataString(e.GetArg("usr"))}\n`Image provided by https://lemmmy.pw/osusig`").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("💢 Failed retrieving osu signature :\\").ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Module.Prefix + "osu b")
|
||||||
|
.Description("Shows information about an osu beatmap.\n**Usage**:~osu b https://osu.ppy.sh/s/127712")
|
||||||
|
.Parameter("map", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(NadekoBot.Creds.OsuAPIKey))
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("💢 An osu! API key is required.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(e.GetArg("map")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var mapId = ResolveMap(e.GetArg("map"));
|
||||||
|
var reqString = $"https://osu.ppy.sh/api/get_beatmaps?k={NadekoBot.Creds.OsuAPIKey}&{mapId}";
|
||||||
|
var obj = JArray.Parse(await SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false))[0];
|
||||||
|
var sb = new System.Text.StringBuilder();
|
||||||
|
var starRating = Math.Round(Double.Parse($"{obj["difficultyrating"]}"), 2);
|
||||||
|
var time = TimeSpan.FromSeconds(Double.Parse($"{obj["total_length"]}")).ToString(@"mm\:ss");
|
||||||
|
sb.AppendLine($"{obj["artist"]} - {obj["title"]}, mapped by {obj["creator"]}. https://osu.ppy.sh/s/{obj["beatmapset_id"]}");
|
||||||
|
sb.AppendLine($"{starRating} stars, {obj["bpm"]} BPM | AR{obj["diff_approach"]}, CS{obj["diff_size"]}, OD{obj["diff_overall"]} | Length: {time}");
|
||||||
|
await e.Channel.SendMessage(sb.ToString()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("Something went wrong.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Module.Prefix + "osu top5")
|
||||||
|
.Description("Displays a user's top 5 plays. \n**Usage**:~osu top5 Name")
|
||||||
|
.Parameter("usr", ParameterType.Required)
|
||||||
|
.Parameter("mode", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(NadekoBot.Creds.OsuAPIKey))
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("💢 An osu! API key is required.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(e.GetArg("usr")))
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("💢 Please provide a username.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var m = 0;
|
||||||
|
if (!string.IsNullOrWhiteSpace(e.GetArg("mode")))
|
||||||
|
{
|
||||||
|
m = ResolveGameMode(e.GetArg("mode"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var reqString = $"https://osu.ppy.sh/api/get_user_best?k={NadekoBot.Creds.OsuAPIKey}&u={Uri.EscapeDataString(e.GetArg("usr"))}&type=string&limit=5&m={m}";
|
||||||
|
var obj = JArray.Parse(await SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false));
|
||||||
|
var sb = new System.Text.StringBuilder($"`Top 5 plays for {e.GetArg("usr")}:`\n```xl" + Environment.NewLine);
|
||||||
|
foreach (var item in obj)
|
||||||
|
{
|
||||||
|
var mapReqString = $"https://osu.ppy.sh/api/get_beatmaps?k={NadekoBot.Creds.OsuAPIKey}&b={item["beatmap_id"]}";
|
||||||
|
var map = JArray.Parse(await SearchHelper.GetResponseStringAsync(mapReqString).ConfigureAwait(false))[0];
|
||||||
|
var pp = Math.Round(Double.Parse($"{item["pp"]}"), 2);
|
||||||
|
var acc = CalculateAcc(item, m);
|
||||||
|
var mods = ResolveMods(Int32.Parse($"{item["enabled_mods"]}"));
|
||||||
|
if (mods != "+")
|
||||||
|
sb.AppendLine($"{pp + "pp",-7} | {acc + "%",-7} | {map["artist"] + "-" + map["title"] + " (" + map["version"],-40}) | **{mods,-10}** | /b/{item["beatmap_id"]}");
|
||||||
|
else
|
||||||
|
sb.AppendLine($"{pp + "pp",-7} | {acc + "%",-7} | {map["artist"] + "-" + map["title"] + " (" + map["version"],-40}) | /b/{item["beatmap_id"]}");
|
||||||
|
}
|
||||||
|
sb.Append("```");
|
||||||
|
await e.Channel.SendMessage(sb.ToString()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("Something went wrong.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//https://osu.ppy.sh/wiki/Accuracy
|
||||||
|
private static Double CalculateAcc(JToken play, int mode)
|
||||||
|
{
|
||||||
|
if (mode == 0)
|
||||||
|
{
|
||||||
|
var hitPoints = Double.Parse($"{play["count50"]}") * 50 + Double.Parse($"{play["count100"]}") * 100 + Double.Parse($"{play["count300"]}") * 300;
|
||||||
|
var totalHits = Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countmiss"]}");
|
||||||
|
totalHits *= 300;
|
||||||
|
return Math.Round(hitPoints / totalHits * 100, 2);
|
||||||
|
}
|
||||||
|
else if (mode == 1)
|
||||||
|
{
|
||||||
|
var hitPoints = Double.Parse($"{play["countmiss"]}") * 0 + Double.Parse($"{play["count100"]}") * 0.5 + Double.Parse($"{play["count300"]}") * 1;
|
||||||
|
var totalHits = Double.Parse($"{play["countmiss"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}");
|
||||||
|
hitPoints *= 300;
|
||||||
|
totalHits *= 300;
|
||||||
|
return Math.Round(hitPoints / totalHits * 100, 2);
|
||||||
|
}
|
||||||
|
else if (mode == 2)
|
||||||
|
{
|
||||||
|
var fruitsCaught = Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}");
|
||||||
|
var totalFruits = Double.Parse($"{play["countmiss"]}") + Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countkatu"]}");
|
||||||
|
return Math.Round(fruitsCaught / totalFruits * 100, 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var hitPoints = Double.Parse($"{play["count50"]}") * 50 + Double.Parse($"{play["count100"]}") * 100 + Double.Parse($"{play["countkatu"]}") * 200 + (Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countgeki"]}")) * 300;
|
||||||
|
var totalHits = Double.Parse($"{play["countmiss"]}") + Double.Parse($"{play["count50"]}") + Double.Parse($"{play["count100"]}") + Double.Parse($"{play["countkatu"]}") + Double.Parse($"{play["count300"]}") + Double.Parse($"{play["countgeki"]}");
|
||||||
|
totalHits *= 300;
|
||||||
|
return Math.Round(hitPoints / totalHits * 100, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveMap(string mapLink)
|
||||||
|
{
|
||||||
|
Match s = new Regex(@"osu.ppy.sh\/s\/", RegexOptions.IgnoreCase).Match(mapLink);
|
||||||
|
Match b = new Regex(@"osu.ppy.sh\/b\/", RegexOptions.IgnoreCase).Match(mapLink);
|
||||||
|
Match p = new Regex(@"osu.ppy.sh\/p\/", RegexOptions.IgnoreCase).Match(mapLink);
|
||||||
|
Match m = new Regex(@"&m=", RegexOptions.IgnoreCase).Match(mapLink);
|
||||||
|
if (s.Success)
|
||||||
|
{
|
||||||
|
var mapId = mapLink.Substring(mapLink.IndexOf("/s/") + 3);
|
||||||
|
return $"s={mapId}";
|
||||||
|
}
|
||||||
|
else if (b.Success)
|
||||||
|
{
|
||||||
|
if (m.Success)
|
||||||
|
return $"b={mapLink.Substring(mapLink.IndexOf("/b/") + 3, mapLink.IndexOf("&m") - (mapLink.IndexOf("/b/") + 3))}";
|
||||||
|
else
|
||||||
|
return $"b={mapLink.Substring(mapLink.IndexOf("/b/") + 3)}";
|
||||||
|
}
|
||||||
|
else if (p.Success)
|
||||||
|
{
|
||||||
|
if (m.Success)
|
||||||
|
return $"b={mapLink.Substring(mapLink.IndexOf("?b=") + 3, mapLink.IndexOf("&m") - (mapLink.IndexOf("?b=") + 3))}";
|
||||||
|
else
|
||||||
|
return $"b={mapLink.Substring(mapLink.IndexOf("?b=") + 3)}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $"s={mapLink}"; //just a default incase an ID number was provided by itself (non-url)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ResolveGameMode(string mode)
|
||||||
|
{
|
||||||
|
switch (mode.ToLower())
|
||||||
|
{
|
||||||
|
case "std":
|
||||||
|
case "standard":
|
||||||
|
return 0;
|
||||||
|
case "taiko":
|
||||||
|
return 1;
|
||||||
|
case "ctb":
|
||||||
|
case "catchthebeat":
|
||||||
|
return 2;
|
||||||
|
case "mania":
|
||||||
|
case "osu!mania":
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//https://github.com/ppy/osu-api/wiki#mods
|
||||||
|
private static string ResolveMods(int mods)
|
||||||
|
{
|
||||||
|
var modString = $"+";
|
||||||
|
|
||||||
|
if (IsBitSet(mods, 0))
|
||||||
|
modString += "NF";
|
||||||
|
if (IsBitSet(mods, 1))
|
||||||
|
modString += "EZ";
|
||||||
|
if (IsBitSet(mods, 8))
|
||||||
|
modString += "HT";
|
||||||
|
|
||||||
|
if (IsBitSet(mods, 3))
|
||||||
|
modString += "HD";
|
||||||
|
if (IsBitSet(mods, 4))
|
||||||
|
modString += "HR";
|
||||||
|
if (IsBitSet(mods, 6) && !IsBitSet(mods, 9))
|
||||||
|
modString += "DT";
|
||||||
|
if (IsBitSet(mods, 9))
|
||||||
|
modString += "NC";
|
||||||
|
if (IsBitSet(mods, 10))
|
||||||
|
modString += "FL";
|
||||||
|
|
||||||
|
if (IsBitSet(mods, 5))
|
||||||
|
modString += "SD";
|
||||||
|
if (IsBitSet(mods, 14))
|
||||||
|
modString += "PF";
|
||||||
|
|
||||||
|
if (IsBitSet(mods, 7))
|
||||||
|
modString += "RX";
|
||||||
|
if (IsBitSet(mods, 11))
|
||||||
|
modString += "AT";
|
||||||
|
if (IsBitSet(mods, 12))
|
||||||
|
modString += "SO";
|
||||||
|
return modString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsBitSet(int mods, int pos)
|
||||||
|
{
|
||||||
|
return (mods & (1 << pos)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
116
NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs
Normal file
116
NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Classes;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Searches.Commands
|
||||||
|
{
|
||||||
|
class PokemonSearchCommands : DiscordCommand
|
||||||
|
{
|
||||||
|
private static Dictionary<string, SearchPokemon> pokemons;
|
||||||
|
private static Dictionary<string, SearchPokemonAbility> pokemonAbilities;
|
||||||
|
|
||||||
|
public PokemonSearchCommands(DiscordModule module) : base(module)
|
||||||
|
{
|
||||||
|
|
||||||
|
pokemons = JsonConvert.DeserializeObject<Dictionary<string, SearchPokemon>>(File.ReadAllText("data/pokemon/pokemon_list.json"));
|
||||||
|
pokemonAbilities = JsonConvert.DeserializeObject<Dictionary<string, SearchPokemonAbility>>(File.ReadAllText("data/pokemon/pokemon_abilities.json"));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Init(CommandGroupBuilder cgb)
|
||||||
|
{
|
||||||
|
cgb.CreateCommand(Prefix + "pokemon")
|
||||||
|
.Alias(Prefix + "poke")
|
||||||
|
.Description("Searches for a pokemon.")
|
||||||
|
.Parameter("pokemon", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var pok = e.GetArg("pokemon")?.Trim().ToUpperInvariant();
|
||||||
|
if (string.IsNullOrWhiteSpace(pok))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var kvp in pokemons)
|
||||||
|
{
|
||||||
|
if (kvp.Key.ToUpperInvariant() == pok.ToUpperInvariant())
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage($"`Stats for \"{kvp.Key}\" pokemon:`\n{kvp.Value}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await e.Channel.SendMessage("`No pokemon found.`");
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "pokemonability")
|
||||||
|
.Alias(Prefix + "pokab")
|
||||||
|
.Description("Searches for a pokemon ability.")
|
||||||
|
.Parameter("abil", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var ab = e.GetArg("abil")?.Trim().ToUpperInvariant();
|
||||||
|
if (string.IsNullOrWhiteSpace(ab))
|
||||||
|
return;
|
||||||
|
foreach (var kvp in pokemonAbilities)
|
||||||
|
{
|
||||||
|
if (kvp.Key.ToUpperInvariant() == ab)
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage($"`Info for \"{kvp.Key}\" ability:`\n{kvp.Value}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await e.Channel.SendMessage("`No ability found.`");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SearchPokemon
|
||||||
|
{
|
||||||
|
public class GenderRatioClass
|
||||||
|
{
|
||||||
|
public float M { get; set; }
|
||||||
|
public float F { get; set; }
|
||||||
|
}
|
||||||
|
public class BaseStatsClass
|
||||||
|
{
|
||||||
|
public int HP { get; set; }
|
||||||
|
public int ATK { get; set; }
|
||||||
|
public int DEF { get; set; }
|
||||||
|
public int SPA { get; set; }
|
||||||
|
public int SPD { get; set; }
|
||||||
|
public int SPE { get; set; }
|
||||||
|
|
||||||
|
public override string ToString() => $@"
|
||||||
|
**HP:** {HP,-4} **ATK:** {ATK,-4} **DEF:** {DEF,-4}
|
||||||
|
**SPA:** {SPA,-4} **SPD:** {SPD,-4} **SPE:** {SPE,-4}";
|
||||||
|
}
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Species { get; set; }
|
||||||
|
public string[] Types { get; set; }
|
||||||
|
public GenderRatioClass GenderRatio { get; set; }
|
||||||
|
public BaseStatsClass BaseStats { get; set; }
|
||||||
|
public Dictionary<string, string> Abilities { get; set; }
|
||||||
|
public float HeightM { get; set; }
|
||||||
|
public float WeightKg { get; set; }
|
||||||
|
public string Color { get; set; }
|
||||||
|
public string[] Evos { get; set; }
|
||||||
|
public string[] EggGroups { get; set; }
|
||||||
|
|
||||||
|
public override string ToString() => $@"`Name:` {Species}
|
||||||
|
`Types:` {string.Join(", ", Types)}
|
||||||
|
`Stats:` {BaseStats}
|
||||||
|
`Height:` {HeightM,4}m `Weight:` {WeightKg}kg
|
||||||
|
`Abilities:` {string.Join(", ", Abilities.Values)}";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SearchPokemonAbility
|
||||||
|
{
|
||||||
|
public string Desc { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public float Rating { get; set; }
|
||||||
|
|
||||||
|
public override string ToString() => $@"`Name:` : {Name}
|
||||||
|
`Rating:` {Rating}
|
||||||
|
`Description:` {Desc}";
|
||||||
|
}
|
||||||
|
}
|
@ -73,7 +73,7 @@ namespace NadekoBot.Modules.Searches.Commands
|
|||||||
checkTimer.Start();
|
checkTimer.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Tuple<bool, string>> GetStreamStatus(StreamNotificationConfig stream)
|
private async Task<Tuple<bool, string>> GetStreamStatus(StreamNotificationConfig stream, bool checkCache = true)
|
||||||
{
|
{
|
||||||
bool isLive;
|
bool isLive;
|
||||||
string response;
|
string response;
|
||||||
@ -83,7 +83,7 @@ namespace NadekoBot.Modules.Searches.Commands
|
|||||||
{
|
{
|
||||||
case StreamNotificationConfig.StreamType.Hitbox:
|
case StreamNotificationConfig.StreamType.Hitbox:
|
||||||
var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username}";
|
var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username}";
|
||||||
if (cachedStatuses.TryGetValue(hitboxUrl, out result))
|
if (checkCache && cachedStatuses.TryGetValue(hitboxUrl, out result))
|
||||||
return result;
|
return result;
|
||||||
response = await SearchHelper.GetResponseStringAsync(hitboxUrl).ConfigureAwait(false);
|
response = await SearchHelper.GetResponseStringAsync(hitboxUrl).ConfigureAwait(false);
|
||||||
data = JObject.Parse(response);
|
data = JObject.Parse(response);
|
||||||
@ -93,7 +93,7 @@ namespace NadekoBot.Modules.Searches.Commands
|
|||||||
return result;
|
return result;
|
||||||
case StreamNotificationConfig.StreamType.Twitch:
|
case StreamNotificationConfig.StreamType.Twitch:
|
||||||
var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username)}";
|
var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username)}";
|
||||||
if (cachedStatuses.TryGetValue(twitchUrl, out result))
|
if (checkCache && cachedStatuses.TryGetValue(twitchUrl, out result))
|
||||||
return result;
|
return result;
|
||||||
response = await SearchHelper.GetResponseStringAsync(twitchUrl).ConfigureAwait(false);
|
response = await SearchHelper.GetResponseStringAsync(twitchUrl).ConfigureAwait(false);
|
||||||
data = JObject.Parse(response);
|
data = JObject.Parse(response);
|
||||||
@ -103,7 +103,7 @@ namespace NadekoBot.Modules.Searches.Commands
|
|||||||
return result;
|
return result;
|
||||||
case StreamNotificationConfig.StreamType.Beam:
|
case StreamNotificationConfig.StreamType.Beam:
|
||||||
var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username}";
|
var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username}";
|
||||||
if (cachedStatuses.TryGetValue(beamUrl, out result))
|
if (checkCache && cachedStatuses.TryGetValue(beamUrl, out result))
|
||||||
return result;
|
return result;
|
||||||
response = await SearchHelper.GetResponseStringAsync(beamUrl).ConfigureAwait(false);
|
response = await SearchHelper.GetResponseStringAsync(beamUrl).ConfigureAwait(false);
|
||||||
data = JObject.Parse(response);
|
data = JObject.Parse(response);
|
||||||
@ -143,6 +143,93 @@ namespace NadekoBot.Modules.Searches.Commands
|
|||||||
.Parameter("username", ParameterType.Unparsed)
|
.Parameter("username", ParameterType.Unparsed)
|
||||||
.Do(TrackStream(StreamNotificationConfig.StreamType.Beam));
|
.Do(TrackStream(StreamNotificationConfig.StreamType.Beam));
|
||||||
|
|
||||||
|
cgb.CreateCommand(Module.Prefix + "checkhitbox")
|
||||||
|
.Alias(Module.Prefix + "chhb")
|
||||||
|
.Description("Checks if a certain user is streaming on the hitbox platform." +
|
||||||
|
"\n**Usage**: ~chhb SomeStreamer")
|
||||||
|
.Parameter("username", ParameterType.Unparsed)
|
||||||
|
.AddCheck(SimpleCheckers.ManageServer())
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var stream = e.GetArg("username")?.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(stream))
|
||||||
|
return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var streamStatus = (await GetStreamStatus(new StreamNotificationConfig
|
||||||
|
{
|
||||||
|
Username = stream,
|
||||||
|
Type = StreamNotificationConfig.StreamType.Hitbox
|
||||||
|
}));
|
||||||
|
if (streamStatus.Item1)
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage($"`Streamer {streamStatus.Item2} is online.`");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("No channel found.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Module.Prefix + "checktwitch")
|
||||||
|
.Alias(Module.Prefix + "chtw")
|
||||||
|
.Description("Checks if a certain user is streaming on the twitch platform." +
|
||||||
|
"\n**Usage**: ~chtw SomeStreamer")
|
||||||
|
.AddCheck(SimpleCheckers.ManageServer())
|
||||||
|
.Parameter("username", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var stream = e.GetArg("username")?.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(stream))
|
||||||
|
return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var streamStatus = (await GetStreamStatus(new StreamNotificationConfig
|
||||||
|
{
|
||||||
|
Username = stream,
|
||||||
|
Type = StreamNotificationConfig.StreamType.Twitch
|
||||||
|
}));
|
||||||
|
if (streamStatus.Item1)
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage($"`Streamer {streamStatus.Item2} is online.`");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("No channel found.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Module.Prefix + "checkbeam")
|
||||||
|
.Alias(Module.Prefix + "chbm")
|
||||||
|
.Description("Checks if a certain user is streaming on the beam platform." +
|
||||||
|
"\n**Usage**: ~chbm SomeStreamer")
|
||||||
|
.AddCheck(SimpleCheckers.ManageServer())
|
||||||
|
.Parameter("username", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var stream = e.GetArg("username")?.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(stream))
|
||||||
|
return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var streamStatus = (await GetStreamStatus(new StreamNotificationConfig
|
||||||
|
{
|
||||||
|
Username = stream,
|
||||||
|
Type = StreamNotificationConfig.StreamType.Beam
|
||||||
|
}));
|
||||||
|
if (streamStatus.Item1)
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage($"`Streamer {streamStatus.Item2} is online.`");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("No channel found.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Module.Prefix + "removestream")
|
cgb.CreateCommand(Module.Prefix + "removestream")
|
||||||
.Alias(Module.Prefix + "rms")
|
.Alias(Module.Prefix + "rms")
|
||||||
.Description("Removes notifications of a certain streamer on this channel." +
|
.Description("Removes notifications of a certain streamer on this channel." +
|
||||||
|
@ -14,7 +14,6 @@ using System.Collections.Generic;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Searches
|
namespace NadekoBot.Modules.Searches
|
||||||
@ -30,6 +29,9 @@ namespace NadekoBot.Modules.Searches
|
|||||||
commands.Add(new RedditCommand(this));
|
commands.Add(new RedditCommand(this));
|
||||||
commands.Add(new WowJokeCommand(this));
|
commands.Add(new WowJokeCommand(this));
|
||||||
commands.Add(new CalcCommand(this));
|
commands.Add(new CalcCommand(this));
|
||||||
|
commands.Add(new OsuCommands(this));
|
||||||
|
commands.Add(new PokemonSearchCommands(this));
|
||||||
|
commands.Add(new MemegenCommands(this));
|
||||||
rng = new Random();
|
rng = new Random();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,10 +191,10 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
|||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(e.GetArg("query"))}&cx=018084019232060951019%3Ahs5piey28-e&num=50&searchType=image&start={ rng.Next(1, 50) }&fields=items%2Flink&key={NadekoBot.Creds.GoogleAPIKey}";
|
var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(e.GetArg("query"))}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&start={ rng.Next(1, 50) }&fields=items%2Flink&key={NadekoBot.Creds.GoogleAPIKey}";
|
||||||
var obj = JObject.Parse(await SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false));
|
var obj = JObject.Parse(await SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false));
|
||||||
var items = obj["items"] as JArray;
|
var items = obj["items"] as JArray;
|
||||||
await e.Channel.SendMessage(items[rng.Next(0, items.Count)]["link"].ToString()).ConfigureAwait(false);
|
await e.Channel.SendMessage(items[0]["link"].ToString()).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (HttpRequestException exception)
|
catch (HttpRequestException exception)
|
||||||
{
|
{
|
||||||
@ -206,6 +208,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "lmgtfy")
|
cgb.CreateCommand(Prefix + "lmgtfy")
|
||||||
.Description("Google something for an idiot.")
|
.Description("Google something for an idiot.")
|
||||||
.Parameter("ffs", ParameterType.Unparsed)
|
.Parameter("ffs", ParameterType.Unparsed)
|
||||||
@ -257,38 +260,6 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "osu")
|
|
||||||
.Description("Shows osu stats for a player.\n**Usage**:~osu Name")
|
|
||||||
.Parameter("usr", ParameterType.Unparsed)
|
|
||||||
.Do(async e =>
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(e.GetArg("usr")))
|
|
||||||
return;
|
|
||||||
|
|
||||||
using (WebClient cl = new WebClient())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
cl.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
|
|
||||||
cl.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/5.0 (Windows NT 6.2; Win64; x64)");
|
|
||||||
cl.DownloadDataAsync(new Uri($"http://lemmmy.pw/osusig/sig.php?uname={ e.GetArg("usr") }&flagshadow&xpbar&xpbarhex&pp=2"));
|
|
||||||
cl.DownloadDataCompleted += async (s, cle) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await e.Channel.SendFile($"{e.GetArg("usr")}.png", new MemoryStream(cle.Result)).ConfigureAwait(false);
|
|
||||||
await e.Channel.SendMessage($"`Profile Link:`https://osu.ppy.sh/u/{Uri.EscapeDataString(e.GetArg("usr"))}\n`Image provided by https://lemmmy.pw/osusig`").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await e.Channel.SendMessage("💢 Failed retrieving osu signature :\\").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
cgb.CreateCommand(Prefix + "ud")
|
cgb.CreateCommand(Prefix + "ud")
|
||||||
.Description("Searches Urban Dictionary for a word.\n**Usage**:~ud Pineapple")
|
.Description("Searches Urban Dictionary for a word.\n**Usage**:~ud Pineapple")
|
||||||
.Parameter("query", ParameterType.Unparsed)
|
.Parameter("query", ParameterType.Unparsed)
|
||||||
@ -505,6 +476,22 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
|||||||
Console.WriteLine(ex);
|
Console.WriteLine(ex);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "av")
|
||||||
|
.Alias(Prefix + "avatar")
|
||||||
|
.Parameter("mention", ParameterType.Required)
|
||||||
|
.Description("Shows a mentioned person's avatar.\n**Usage**: ~av @X")
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var usr = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault();
|
||||||
|
if (usr == null)
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage("Invalid user specified.").ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await e.Channel.SendMessage(await usr.AvatarUrl.ShortenUrl()).ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,12 @@
|
|||||||
// License: Code Project Open License
|
// License: Code Project Open License
|
||||||
// http://www.codeproject.com/info/cpol10.aspx
|
// http://www.codeproject.com/info/cpol10.aspx
|
||||||
|
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Translator.Helpers
|
namespace NadekoBot.Modules.Translator.Helpers
|
||||||
@ -26,32 +28,6 @@ namespace NadekoBot.Modules.Translator.Helpers
|
|||||||
return GoogleTranslator._languageModeMap.Keys.OrderBy(p => p);
|
return GoogleTranslator._languageModeMap.Keys.OrderBy(p => p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the time taken to perform the translation.
|
|
||||||
/// </summary>
|
|
||||||
public TimeSpan TranslationTime {
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the url used to speak the translation.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The url used to speak the translation.</value>
|
|
||||||
public string TranslationSpeechUrl {
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the error.
|
|
||||||
/// </summary>
|
|
||||||
public Exception Error {
|
|
||||||
get;
|
|
||||||
private set;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Public methods
|
#region Public methods
|
||||||
@ -63,92 +39,28 @@ namespace NadekoBot.Modules.Translator.Helpers
|
|||||||
/// <param name="sourceLanguage">The source language.</param>
|
/// <param name="sourceLanguage">The source language.</param>
|
||||||
/// <param name="targetLanguage">The target language.</param>
|
/// <param name="targetLanguage">The target language.</param>
|
||||||
/// <returns>The translation.</returns>
|
/// <returns>The translation.</returns>
|
||||||
public string Translate
|
public async Task<string> Translate
|
||||||
(string sourceText,
|
(string sourceText,
|
||||||
string sourceLanguage,
|
string sourceLanguage,
|
||||||
string targetLanguage)
|
string targetLanguage)
|
||||||
{
|
{
|
||||||
// Initialize
|
// Initialize
|
||||||
this.Error = null;
|
|
||||||
this.TranslationSpeechUrl = null;
|
|
||||||
this.TranslationTime = TimeSpan.Zero;
|
|
||||||
DateTime tmStart = DateTime.Now;
|
DateTime tmStart = DateTime.Now;
|
||||||
string translation = string.Empty;
|
|
||||||
string text = string.Empty;
|
string text = string.Empty;
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Download translation
|
// Download translation
|
||||||
string url = string.Format("https://translate.googleapis.com/translate_a/single?client=gtx&sl={0}&tl={1}&dt=t&q={2}",
|
string url = string.Format("https://translate.googleapis.com/translate_a/single?client=gtx&sl={0}&tl={1}&dt=t&q={2}",
|
||||||
GoogleTranslator.LanguageEnumToIdentifier(sourceLanguage),
|
GoogleTranslator.LanguageEnumToIdentifier(sourceLanguage),
|
||||||
GoogleTranslator.LanguageEnumToIdentifier(targetLanguage),
|
GoogleTranslator.LanguageEnumToIdentifier(targetLanguage),
|
||||||
HttpUtility.UrlEncode(sourceText));
|
HttpUtility.UrlEncode(sourceText));
|
||||||
using (WebClient wc = new WebClient())
|
using (HttpClient http = new HttpClient())
|
||||||
{
|
{
|
||||||
wc.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36");
|
http.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36");
|
||||||
text = wc.DownloadString(url);
|
text = await http.GetStringAsync(url).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get translated text
|
return JArray.Parse(text)[0][0][0].ToString();
|
||||||
// Get phrase collection
|
|
||||||
// string text = File.ReadAllText(outputFile);
|
|
||||||
int index = text.IndexOf(string.Format(",,\"{0}\"", GoogleTranslator.LanguageEnumToIdentifier(sourceLanguage)));
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
// Translation of single word
|
|
||||||
int startQuote = text.IndexOf('\"');
|
|
||||||
if (startQuote != -1)
|
|
||||||
{
|
|
||||||
int endQuote = text.IndexOf('\"', startQuote + 1);
|
|
||||||
if (endQuote != -1)
|
|
||||||
{
|
|
||||||
translation = text.Substring(startQuote + 1, endQuote - startQuote - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Translation of phrase
|
|
||||||
text = text.Substring(0, index);
|
|
||||||
text = text.Replace("],[", ",");
|
|
||||||
text = text.Replace("]", string.Empty);
|
|
||||||
text = text.Replace("[", string.Empty);
|
|
||||||
text = text.Replace("\",\"", "\"");
|
|
||||||
|
|
||||||
// Get translated phrases
|
|
||||||
string[] phrases = text.Split(new[] { '\"' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
for (int i = 0; (i < phrases.Count()); i += 2)
|
|
||||||
{
|
|
||||||
string translatedPhrase = phrases[i];
|
|
||||||
if (translatedPhrase.StartsWith(",,"))
|
|
||||||
{
|
|
||||||
i--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
translation += translatedPhrase + " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix up translation
|
|
||||||
translation = translation.Trim();
|
|
||||||
translation = translation.Replace(" ?", "?");
|
|
||||||
translation = translation.Replace(" !", "!");
|
|
||||||
translation = translation.Replace(" ,", ",");
|
|
||||||
translation = translation.Replace(" .", ".");
|
|
||||||
translation = translation.Replace(" ;", ";");
|
|
||||||
|
|
||||||
// And translation speech URL
|
|
||||||
this.TranslationSpeechUrl = string.Format("https://translate.googleapis.com/translate_tts?ie=UTF-8&q={0}&tl={1}&total=1&idx=0&textlen={2}&client=gtx",
|
|
||||||
HttpUtility.UrlEncode(translation), GoogleTranslator.LanguageEnumToIdentifier(targetLanguage), translation.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
this.Error = ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return result
|
|
||||||
this.TranslationTime = DateTime.Now - tmStart;
|
|
||||||
return translation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -27,13 +27,17 @@ namespace NadekoBot.Modules.Translator
|
|||||||
await e.Channel.SendIsTyping().ConfigureAwait(false);
|
await e.Channel.SendIsTyping().ConfigureAwait(false);
|
||||||
string from = e.GetArg("langs").ToLowerInvariant().Split('>')[0];
|
string from = e.GetArg("langs").ToLowerInvariant().Split('>')[0];
|
||||||
string to = e.GetArg("langs").ToLowerInvariant().Split('>')[1];
|
string to = e.GetArg("langs").ToLowerInvariant().Split('>')[1];
|
||||||
|
var text = e.GetArg("text")?.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
|
return;
|
||||||
|
|
||||||
string translation = t.Translate(e.GetArg("text"), from, to);
|
string translation = await t.Translate(text, from, to).ConfigureAwait(false);
|
||||||
await e.Channel.SendMessage(translation).ConfigureAwait(false);
|
await e.Channel.SendMessage(translation).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await e.Channel.SendMessage("Bad input format, or sth went wrong...").ConfigureAwait(false);
|
Console.WriteLine(ex);
|
||||||
|
await e.Channel.SendMessage("Bad input format, or something went wrong...").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,7 @@ using System;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration.Commands
|
namespace NadekoBot.Modules.Utility.Commands
|
||||||
{
|
{
|
||||||
class InfoCommands : DiscordCommand
|
class InfoCommands : DiscordCommand
|
||||||
{
|
{
|
@ -9,7 +9,7 @@ using System.Linq;
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration.Commands
|
namespace NadekoBot.Modules.Utility.Commands
|
||||||
{
|
{
|
||||||
class Remind : DiscordCommand
|
class Remind : DiscordCommand
|
||||||
{
|
{
|
151
NadekoBot/Modules/Utility/UtilityModule.cs
Normal file
151
NadekoBot/Modules/Utility/UtilityModule.cs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using Discord.Modules;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Modules.Permissions.Classes;
|
||||||
|
using NadekoBot.Modules.Utility.Commands;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Utility
|
||||||
|
{
|
||||||
|
internal class UtilityModule : DiscordModule
|
||||||
|
{
|
||||||
|
public UtilityModule()
|
||||||
|
{
|
||||||
|
commands.Add(new Remind(this));
|
||||||
|
commands.Add(new InfoCommands(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Prefix => NadekoBot.Config.CommandPrefixes.Utility;
|
||||||
|
|
||||||
|
public override void Install(ModuleManager manager)
|
||||||
|
{
|
||||||
|
|
||||||
|
manager.CreateCommands("", cgb =>
|
||||||
|
{
|
||||||
|
cgb.AddCheck(PermissionChecker.Instance);
|
||||||
|
|
||||||
|
var client = manager.Client;
|
||||||
|
|
||||||
|
commands.ForEach(cmd => cmd.Init(cgb));
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "whoplays")
|
||||||
|
.Description("Shows a list of users who are playing the specified game.")
|
||||||
|
.Parameter("game", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var game = e.GetArg("game")?.Trim().ToUpperInvariant();
|
||||||
|
if (string.IsNullOrWhiteSpace(game))
|
||||||
|
return;
|
||||||
|
var en = e.Server.Users
|
||||||
|
.Where(u => u.CurrentGame?.Name?.ToUpperInvariant() == game)
|
||||||
|
.Select(u => u.Name);
|
||||||
|
|
||||||
|
var arr = en as string[] ?? en.ToArray();
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
if (arr.Length == 0)
|
||||||
|
await e.Channel.SendMessage("Nobody. (not 100% sure)").ConfigureAwait(false);
|
||||||
|
else
|
||||||
|
await e.Channel.SendMessage("```xl\n" + string.Join("\n", arr.GroupBy(item => (i++) / 3).Select(ig => string.Join("", ig.Select(el => $"• {el,-35}")))) + "\n```").ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "inrole")
|
||||||
|
.Description("Lists every person from the provided role or roles (separated by a ',') on this server.")
|
||||||
|
.Parameter("roles", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
await Task.Run(async () =>
|
||||||
|
{
|
||||||
|
if (!e.User.ServerPermissions.MentionEveryone) return;
|
||||||
|
var arg = e.GetArg("roles").Split(',').Select(r => r.Trim());
|
||||||
|
string send = $"`Here is a list of users in a specfic role:`";
|
||||||
|
foreach (var roleStr in arg.Where(str => !string.IsNullOrWhiteSpace(str)))
|
||||||
|
{
|
||||||
|
var role = e.Server.FindRoles(roleStr).FirstOrDefault();
|
||||||
|
if (role == null) continue;
|
||||||
|
send += $"\n`{role.Name}`\n";
|
||||||
|
send += string.Join(", ", role.Members.Select(r => "**" + r.Name + "**#" + r.Discriminator));
|
||||||
|
}
|
||||||
|
|
||||||
|
while (send.Length > 2000)
|
||||||
|
{
|
||||||
|
var curstr = send.Substring(0, 2000);
|
||||||
|
await
|
||||||
|
e.Channel.Send(curstr.Substring(0,
|
||||||
|
curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1)).ConfigureAwait(false);
|
||||||
|
send = curstr.Substring(curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1) +
|
||||||
|
send.Substring(2000);
|
||||||
|
}
|
||||||
|
await e.Channel.Send(send).ConfigureAwait(false);
|
||||||
|
}).ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "checkmyperms")
|
||||||
|
.Description("Checks your userspecific permissions on this channel.")
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var output = "```\n";
|
||||||
|
foreach (var p in e.User.ServerPermissions.GetType().GetProperties().Where(p => !p.GetGetMethod().GetParameters().Any()))
|
||||||
|
{
|
||||||
|
output += p.Name + ": " + p.GetValue(e.User.ServerPermissions, null).ToString() + "\n";
|
||||||
|
}
|
||||||
|
output += "```";
|
||||||
|
await e.User.SendMessage(output).ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "stats")
|
||||||
|
.Description("Shows some basic stats for Nadeko.")
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage(await NadekoStats.Instance.GetStats());
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "dysyd")
|
||||||
|
.Description("Shows some basic stats for Nadeko.")
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
await e.Channel.SendMessage((await NadekoStats.Instance.GetStats()).Matrix().TrimTo(1990)).ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "userid").Alias(Prefix + "uid")
|
||||||
|
.Description("Shows user ID.")
|
||||||
|
.Parameter("user", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
var usr = e.User;
|
||||||
|
if (!string.IsNullOrWhiteSpace(e.GetArg("user"))) usr = e.Channel.FindUsers(e.GetArg("user")).FirstOrDefault();
|
||||||
|
if (usr == null)
|
||||||
|
return;
|
||||||
|
await e.Channel.SendMessage($"Id of the user { usr.Name } is { usr.Id }").ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "channelid").Alias(Prefix + "cid")
|
||||||
|
.Description("Shows current channel ID.")
|
||||||
|
.Do(async e => await e.Channel.SendMessage("This channel's ID is " + e.Channel.Id).ConfigureAwait(false));
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "serverid").Alias(Prefix + "sid")
|
||||||
|
.Description("Shows current server ID.")
|
||||||
|
.Do(async e => await e.Channel.SendMessage("This server's ID is " + e.Server.Id).ConfigureAwait(false));
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "roles")
|
||||||
|
.Description("List all roles on this server or a single user if specified.")
|
||||||
|
.Parameter("user", ParameterType.Unparsed)
|
||||||
|
.Do(async e =>
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(e.GetArg("user")))
|
||||||
|
{
|
||||||
|
var usr = e.Server.FindUsers(e.GetArg("user")).FirstOrDefault();
|
||||||
|
if (usr == null) return;
|
||||||
|
|
||||||
|
await e.Channel.SendMessage($"`List of roles for **{usr.Name}**:` \n• " + string.Join("\n• ", usr.Roles)).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await e.Channel.SendMessage("`List of roles:` \n• " + string.Join("\n• ", e.Server.Roles)).ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,7 @@ using NadekoBot.Modules.Pokemon;
|
|||||||
using NadekoBot.Modules.Searches;
|
using NadekoBot.Modules.Searches;
|
||||||
using NadekoBot.Modules.Translator;
|
using NadekoBot.Modules.Translator;
|
||||||
using NadekoBot.Modules.Trello;
|
using NadekoBot.Modules.Trello;
|
||||||
|
using NadekoBot.Modules.Utility;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@ -105,6 +106,9 @@ namespace NadekoBot
|
|||||||
Console.WriteLine(string.IsNullOrWhiteSpace(Creds.SoundCloudClientID)
|
Console.WriteLine(string.IsNullOrWhiteSpace(Creds.SoundCloudClientID)
|
||||||
? "No soundcloud Client ID found. Soundcloud streaming is disabled."
|
? "No soundcloud Client ID found. Soundcloud streaming is disabled."
|
||||||
: "SoundCloud streaming enabled.");
|
: "SoundCloud streaming enabled.");
|
||||||
|
Console.WriteLine(string.IsNullOrWhiteSpace(Creds.OsuAPIKey)
|
||||||
|
? "No osu! api key found. Song & top score lookups will not work. User lookups still available."
|
||||||
|
: "osu! API key provided.");
|
||||||
|
|
||||||
BotMention = $"<@{Creds.BotId}>";
|
BotMention = $"<@{Creds.BotId}>";
|
||||||
|
|
||||||
@ -160,6 +164,7 @@ namespace NadekoBot
|
|||||||
//install modules
|
//install modules
|
||||||
modules.Add(new HelpModule(), "Help", ModuleFilter.None);
|
modules.Add(new HelpModule(), "Help", ModuleFilter.None);
|
||||||
modules.Add(new AdministrationModule(), "Administration", ModuleFilter.None);
|
modules.Add(new AdministrationModule(), "Administration", ModuleFilter.None);
|
||||||
|
modules.Add(new UtilityModule(), "Utility", ModuleFilter.None);
|
||||||
modules.Add(new PermissionModule(), "Permissions", ModuleFilter.None);
|
modules.Add(new PermissionModule(), "Permissions", ModuleFilter.None);
|
||||||
modules.Add(new Conversations(), "Conversations", ModuleFilter.None);
|
modules.Add(new Conversations(), "Conversations", ModuleFilter.None);
|
||||||
modules.Add(new GamblingModule(), "Gambling", ModuleFilter.None);
|
modules.Add(new GamblingModule(), "Gambling", ModuleFilter.None);
|
||||||
|
@ -134,8 +134,10 @@
|
|||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Classes\ObservableConcurrentDictionary.cs" />
|
||||||
<Compile Include="Modules\Administration\Commands\AutoAssignRole.cs" />
|
<Compile Include="Modules\Administration\Commands\AutoAssignRole.cs" />
|
||||||
<Compile Include="Modules\Administration\Commands\CustomReactionsCommands.cs" />
|
<Compile Include="Modules\Administration\Commands\CustomReactionsCommands.cs" />
|
||||||
|
<Compile Include="Modules\Administration\Commands\SelfAssignedRolesCommand.cs" />
|
||||||
<Compile Include="Modules\Administration\Commands\SelfCommands.cs" />
|
<Compile Include="Modules\Administration\Commands\SelfCommands.cs" />
|
||||||
<Compile Include="Modules\ClashOfClans\ClashOfClans.cs" />
|
<Compile Include="Modules\ClashOfClans\ClashOfClans.cs" />
|
||||||
<Compile Include="Classes\DBHandler.cs" />
|
<Compile Include="Classes\DBHandler.cs" />
|
||||||
@ -148,6 +150,11 @@
|
|||||||
<Compile Include="Modules\Searches\Commands\IMDB\ImdbMovie.cs" />
|
<Compile Include="Modules\Searches\Commands\IMDB\ImdbMovie.cs" />
|
||||||
<Compile Include="Modules\Searches\Commands\IMDB\ImdbScraper.cs" />
|
<Compile Include="Modules\Searches\Commands\IMDB\ImdbScraper.cs" />
|
||||||
<Compile Include="Classes\IncidentsHandler.cs" />
|
<Compile Include="Classes\IncidentsHandler.cs" />
|
||||||
|
<Compile Include="Modules\Searches\Commands\MemegenCommands.cs" />
|
||||||
|
<Compile Include="Modules\Searches\Commands\OsuCommands.cs" />
|
||||||
|
<Compile Include="Modules\Searches\Commands\PokemonSearchCommands.cs" />
|
||||||
|
<Compile Include="Modules\Utility\UtilityModule.cs" />
|
||||||
|
<Compile Include="_Models\DataModels\Incident.cs" />
|
||||||
<Compile Include="_Models\JSONModels\AnimeResult.cs" />
|
<Compile Include="_Models\JSONModels\AnimeResult.cs" />
|
||||||
<Compile Include="_Models\JSONModels\Configuration.cs" />
|
<Compile Include="_Models\JSONModels\Configuration.cs" />
|
||||||
<Compile Include="Modules\Searches\Commands\WowJokes.cs" />
|
<Compile Include="Modules\Searches\Commands\WowJokes.cs" />
|
||||||
@ -186,9 +193,9 @@
|
|||||||
<Compile Include="Modules\DiscordCommand.cs" />
|
<Compile Include="Modules\DiscordCommand.cs" />
|
||||||
<Compile Include="Modules\Games\Commands\PlantPick.cs" />
|
<Compile Include="Modules\Games\Commands\PlantPick.cs" />
|
||||||
<Compile Include="Modules\Administration\Commands\CrossServerTextChannel.cs" />
|
<Compile Include="Modules\Administration\Commands\CrossServerTextChannel.cs" />
|
||||||
<Compile Include="Modules\Administration\Commands\InfoCommands.cs" />
|
<Compile Include="Modules\Utility\Commands\InfoCommands.cs" />
|
||||||
<Compile Include="Modules\Administration\Commands\Remind.cs" />
|
<Compile Include="Modules\Utility\Commands\Remind.cs" />
|
||||||
<Compile Include="Modules\Administration\Commands\SelfAssignedRolesCommand.cs" />
|
<Compile Include="Modules\Administration\Commands\IncidentsCommands.cs" />
|
||||||
<Compile Include="Modules\ClashOfClans\ClashOfClansModule.cs" />
|
<Compile Include="Modules\ClashOfClans\ClashOfClansModule.cs" />
|
||||||
<Compile Include="Modules\Permissions\Commands\FilterWordsCommand.cs" />
|
<Compile Include="Modules\Permissions\Commands\FilterWordsCommand.cs" />
|
||||||
<Compile Include="Modules\Permissions\Commands\FilterInvitesCommand.cs" />
|
<Compile Include="Modules\Permissions\Commands\FilterInvitesCommand.cs" />
|
||||||
@ -205,7 +212,6 @@
|
|||||||
<Compile Include="Modules\Games\Commands\SpeedTyping.cs" />
|
<Compile Include="Modules\Games\Commands\SpeedTyping.cs" />
|
||||||
<Compile Include="Modules\Gambling\Helpers\Cards.cs" />
|
<Compile Include="Modules\Gambling\Helpers\Cards.cs" />
|
||||||
<Compile Include="Classes\Extensions.cs" />
|
<Compile Include="Classes\Extensions.cs" />
|
||||||
<Compile Include="Modules\Conversations\Commands\CopyCommand.cs" />
|
|
||||||
<Compile Include="Modules\Gambling\DiceRollCommand.cs" />
|
<Compile Include="Modules\Gambling\DiceRollCommand.cs" />
|
||||||
<Compile Include="Modules\Gambling\DrawCommand.cs" />
|
<Compile Include="Modules\Gambling\DrawCommand.cs" />
|
||||||
<Compile Include="Modules\Gambling\FlipCoinCommand.cs" />
|
<Compile Include="Modules\Gambling\FlipCoinCommand.cs" />
|
||||||
@ -491,9 +497,10 @@
|
|||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="lib\ScaredFingers.UnitsConversion.dll" />
|
<Content Include="Classes\lib\ScaredFingers.UnitsConversion.dll" />
|
||||||
<None Include="resources\images\rose_overlay.png" />
|
<None Include="resources\images\rose_overlay.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
10
NadekoBot/_Models/DataModels/Incident.cs
Normal file
10
NadekoBot/_Models/DataModels/Incident.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace NadekoBot.DataModels
|
||||||
|
{
|
||||||
|
class Incident : IDataModel
|
||||||
|
{
|
||||||
|
public long ServerId { get; set; }
|
||||||
|
public long ChannelId { get; set; }
|
||||||
|
public string Text { get; set; }
|
||||||
|
public bool Read { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
@ -161,6 +161,7 @@ Nadeko Support Server: <https://discord.gg/0ehQwTK2RBjAxzEY>";
|
|||||||
public string Permissions { get; set; } = ";";
|
public string Permissions { get; set; } = ";";
|
||||||
public string Programming { get; set; } = "%";
|
public string Programming { get; set; } = "%";
|
||||||
public string Pokemon { get; set; } = ">";
|
public string Pokemon { get; set; } = ">";
|
||||||
|
public string Utility { get; set; } = ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ConfigHandler
|
public static class ConfigHandler
|
||||||
|
@ -16,6 +16,7 @@ namespace NadekoBot.Classes.JSONModels
|
|||||||
public string LOLAPIKey { get; set; } = "";
|
public string LOLAPIKey { get; set; } = "";
|
||||||
public string TrelloAppKey { get; set; } = "";
|
public string TrelloAppKey { get; set; } = "";
|
||||||
public string CarbonKey { get; set; } = "";
|
public string CarbonKey { get; set; } = "";
|
||||||
|
public string OsuAPIKey { get; set; } = "";
|
||||||
}
|
}
|
||||||
[DebuggerDisplay("{items[0].id.playlistId}")]
|
[DebuggerDisplay("{items[0].id.playlistId}")]
|
||||||
public class YoutubePlaylistSearch
|
public class YoutubePlaylistSearch
|
||||||
|
@ -11,5 +11,6 @@
|
|||||||
"MashapeKey": "",
|
"MashapeKey": "",
|
||||||
"LOLAPIKey": "",
|
"LOLAPIKey": "",
|
||||||
"TrelloAppKey": "",
|
"TrelloAppKey": "",
|
||||||
"CarbonKey": ""
|
"CarbonKey": "",
|
||||||
|
"OsuAPIKey": ""
|
||||||
}
|
}
|
@ -87,7 +87,8 @@
|
|||||||
"Gambling": "$",
|
"Gambling": "$",
|
||||||
"Permissions": ";",
|
"Permissions": ";",
|
||||||
"Programming": "%",
|
"Programming": "%",
|
||||||
"Pokemon": ">"
|
"Pokemon": ">",
|
||||||
|
"Utility": "."
|
||||||
},
|
},
|
||||||
"ServerBlacklist": [],
|
"ServerBlacklist": [],
|
||||||
"ChannelBlacklist": [],
|
"ChannelBlacklist": [],
|
||||||
|
125
commandlist.md
125
commandlist.md
@ -2,7 +2,7 @@
|
|||||||
######You can donate on paypal: `nadekodiscordbot@gmail.com` or Bitcoin `17MZz1JAqME39akMLrVT4XBPffQJ2n1EPa`
|
######You can donate on paypal: `nadekodiscordbot@gmail.com` or Bitcoin `17MZz1JAqME39akMLrVT4XBPffQJ2n1EPa`
|
||||||
|
|
||||||
#NadekoBot List Of Commands
|
#NadekoBot List Of Commands
|
||||||
Version: `NadekoBot v0.9.6015.37609`
|
Version: `NadekoBot v0.9.6029.16666`
|
||||||
### Help
|
### Help
|
||||||
Command and aliases | Description | Usage
|
Command and aliases | Description | Usage
|
||||||
----------------|--------------|-------
|
----------------|--------------|-------
|
||||||
@ -44,16 +44,16 @@ Command and aliases | Description | Usage
|
|||||||
`.lsar` | Lists all self-assignable roles.
|
`.lsar` | Lists all self-assignable roles.
|
||||||
`.iam` | Adds a role to you that you choose. Role must be on a list of self-assignable roles. | .iam Gamer
|
`.iam` | Adds a role to you that you choose. Role must be on a list of self-assignable roles. | .iam Gamer
|
||||||
`.iamnot`, `.iamn` | Removes a role to you that you choose. Role must be on a list of self-assignable roles. | .iamn Gamer
|
`.iamnot`, `.iamn` | Removes a role to you that you choose. Role must be on a list of self-assignable roles. | .iamn Gamer
|
||||||
`.remind` | Sends a message to you or a channel after certain amount of time. First argument is me/here/'channelname'. Second argument is time in a descending order (mo>w>d>h>m) example: 1w5d3h10m. Third argument is a (multiword)message. | `.remind me 1d5h Do something` or `.remind #general Start now!`
|
|
||||||
`.remindmsg` | Sets message for when the remind is triggered. Available placeholders are %user% - user who ran the command, %message% - Message specified in the remind, %target% - target channel of the remind. **Bot Owner Only!**
|
|
||||||
`.serverinfo`, `.sinfo` | Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. | .sinfo Some Server
|
|
||||||
`.channelinfo`, `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | .cinfo #some-channel
|
|
||||||
`.userinfo`, `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | .uinfo @SomeUser
|
|
||||||
`.addcustreact`, `.acr` | Add a custom reaction. Guide here: <https://github.com/Kwoth/NadekoBot/wiki/Custom-Reactions> **Bot Owner Only!** | .acr "hello" I love saying hello to %user%
|
`.addcustreact`, `.acr` | Add a custom reaction. Guide here: <https://github.com/Kwoth/NadekoBot/wiki/Custom-Reactions> **Bot Owner Only!** | .acr "hello" I love saying hello to %user%
|
||||||
`.listcustreact`, `.lcr` | Lists all current custom reactions (paginated with 5 commands per page). | .lcr 1
|
`.listcustreact`, `.lcr` | Lists all current custom reactions (paginated with 30 commands per page). | .lcr 1
|
||||||
|
`.showcustreact`, `.scr` | Shows all possible responses from a single custom reaction. | .scr %mention% bb
|
||||||
|
`.editcustreact`, `.ecr` | Edits a custom reaction, arguments are custom reactions name, index to change, and a (multiword) message **Bot Owner Only** | `.ecr "%mention% disguise" 2 Test 123`
|
||||||
`.delcustreact`, `.dcr` | Deletes a custom reaction with given name (and index)
|
`.delcustreact`, `.dcr` | Deletes a custom reaction with given name (and index)
|
||||||
`.autoassignrole`, `.aar` | Automaticaly assigns a specified role to every user who joins the server. Type `.aar` to disable, `.aar Role Name` to enable
|
`.autoassignrole`, `.aar` | Automaticaly assigns a specified role to every user who joins the server. Type `.aar` to disable, `.aar Role Name` to enable
|
||||||
`.leave` | Makes Nadeko leave the server. Either name or id required. | `.leave 123123123331`
|
`.leave` | Makes Nadeko leave the server. Either name or id required. | `.leave 123123123331`
|
||||||
|
`.listincidents`, `.lin` | List all UNREAD incidents and flags them as read.
|
||||||
|
`.listallincidents`, `.lain` | Sends you a file containing all incidents and flags them as read.
|
||||||
|
`.delmsgoncmd` | Toggles the automatic deletion of user's successful command message to prevent chat flood. Server Manager Only.
|
||||||
`.restart` | Restarts the bot. Might not work.
|
`.restart` | Restarts the bot. Might not work.
|
||||||
`.setrole`, `.sr` | Sets a role for a given user. | .sr @User Guest
|
`.setrole`, `.sr` | Sets a role for a given user. | .sr @User Guest
|
||||||
`.removerole`, `.rr` | Removes a role from a given user. | .rr @User Admin
|
`.removerole`, `.rr` | Removes a role from a given user. | .rr @User Admin
|
||||||
@ -61,7 +61,6 @@ Command and aliases | Description | Usage
|
|||||||
`.removeallroles`, `.rar` | Removes all roles from a mentioned user. | .rar @User
|
`.removeallroles`, `.rar` | Removes all roles from a mentioned user. | .rar @User
|
||||||
`.createrole`, `.cr` | Creates a role with a given name. | `.r Awesome Role`
|
`.createrole`, `.cr` | Creates a role with a given name. | `.r Awesome Role`
|
||||||
`.rolecolor`, `.rc` | Set a role's color to the hex or 0-255 rgb color value provided. | `.color Admin 255 200 100` or `.color Admin ffba55`
|
`.rolecolor`, `.rc` | Set a role's color to the hex or 0-255 rgb color value provided. | `.color Admin 255 200 100` or `.color Admin ffba55`
|
||||||
`.roles` | List all roles on this server or a single user if specified.
|
|
||||||
`.ban`, `.b` | Bans a user by id or name with an optional message. | .b "@some Guy" Your behaviour is toxic.
|
`.ban`, `.b` | Bans a user by id or name with an optional message. | .b "@some Guy" Your behaviour is toxic.
|
||||||
`.softban`, `.sb` | Bans and then unbans a user by id or name with an optional message. | .sb "@some Guy" Your behaviour is toxic.
|
`.softban`, `.sb` | Bans and then unbans a user by id or name with an optional message. | .sb "@some Guy" Your behaviour is toxic.
|
||||||
`.kick`, `.k` | Kicks a mentioned user.
|
`.kick`, `.k` | Kicks a mentioned user.
|
||||||
@ -75,30 +74,38 @@ Command and aliases | Description | Usage
|
|||||||
`.creatxtchanl`, `.ctch` | Creates a new text channel with a given name.
|
`.creatxtchanl`, `.ctch` | Creates a new text channel with a given name.
|
||||||
`.settopic`, `.st` | Sets a topic on the current channel. | `.st My new topic`
|
`.settopic`, `.st` | Sets a topic on the current channel. | `.st My new topic`
|
||||||
`.setchanlname`, `.schn` | Changed the name of the current channel.
|
`.setchanlname`, `.schn` | Changed the name of the current channel.
|
||||||
`.userid`, `.uid` | Shows user ID.
|
|
||||||
`.channelid`, `.cid` | Shows current channel ID.
|
|
||||||
`.serverid`, `.sid` | Shows current server ID.
|
|
||||||
`.stats` | Shows some basic stats for Nadeko.
|
|
||||||
`.dysyd` | Shows some basic stats for Nadeko.
|
|
||||||
`.heap` | Shows allocated memory - **Bot Owner Only!**
|
`.heap` | Shows allocated memory - **Bot Owner Only!**
|
||||||
`.prune`, `.clr` | `.prune` removes all nadeko's messages in the last 100 messages.`.prune X` removes last X messages from the channel (up to 100)`.prune @Someone` removes all Someone's messages in the last 100 messages.`.prune @Someone X` removes last X 'Someone's' messages in the channel. | `.prune` or `.prune 5` or `.prune @Someone` or `.prune @Someone X`
|
`.prune`, `.clr` | `.prune` removes all nadeko's messages in the last 100 messages.`.prune X` removes last X messages from the channel (up to 100)`.prune @Someone` removes all Someone's messages in the last 100 messages.`.prune @Someone X` removes last X 'Someone's' messages in the channel. | `.prune` or `.prune 5` or `.prune @Someone` or `.prune @Someone X`
|
||||||
`.die` | Shuts the bot down and notifies users about the restart. **Bot Owner Only!**
|
`.die` | Shuts the bot down and notifies users about the restart. **Bot Owner Only!**
|
||||||
`.setname`, `.newnm` | Give the bot a new name. **Bot Owner Only!**
|
`.setname`, `.newnm` | Give the bot a new name. **Bot Owner Only!**
|
||||||
`.newavatar`, `.setavatar` | Sets a new avatar image for the NadekoBot. **Bot Owner Only!**
|
`.newavatar`, `.setavatar` | Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot Owner Only!** | `.setavatar https://i.ytimg.com/vi/WDudkR1eTMM/maxresdefault.jpg`
|
||||||
`.setgame` | Sets the bots game. **Bot Owner Only!**
|
`.setgame` | Sets the bots game. **Bot Owner Only!**
|
||||||
`.checkmyperms` | Checks your userspecific permissions on this channel.
|
`.send` | Send a message to someone on a different server through the bot. **Bot Owner Only!** | `.send serverid|u:user_id Send this to a user!` or `.send serverid|c:channel_id Send this to a channel!`
|
||||||
`.commsuser` | Sets a user for through-bot communication. Only works if server is set. Resets commschannel. **Bot Owner Only!**
|
|
||||||
`.commsserver` | Sets a server for through-bot communication. **Bot Owner Only!**
|
|
||||||
`.commschannel` | Sets a channel for through-bot communication. Only works if server is set. Resets commsuser. **Bot Owner Only!**
|
|
||||||
`.send` | Send a message to someone on a different server through the bot. **Bot Owner Only!** | .send Message text multi word!
|
|
||||||
`.mentionrole`, `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have mention everyone permission.
|
`.mentionrole`, `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have mention everyone permission.
|
||||||
`.inrole` | Lists every person from the provided role or roles (separated by a ',') on this server.
|
|
||||||
`.unstuck` | Clears the message queue. **Bot Owner Only!**
|
`.unstuck` | Clears the message queue. **Bot Owner Only!**
|
||||||
`.donators` | List of lovely people who donated to keep this project alive.
|
`.donators` | List of lovely people who donated to keep this project alive.
|
||||||
`.donadd` | Add a donator to the database.
|
`.donadd` | Add a donator to the database.
|
||||||
`.announce` | Sends a message to all servers' general channel bot is connected to.**Bot Owner Only!** | .announce Useless spam
|
`.announce` | Sends a message to all servers' general channel bot is connected to.**Bot Owner Only!** | .announce Useless spam
|
||||||
`.whoplays` | Shows a list of users who are playing the specified game.
|
|
||||||
`.leave` | Leaves a server with a supplied ID. | `.leave 493243292839`
|
`.leave` | Leaves a server with a supplied ID. | `.leave 493243292839`
|
||||||
|
`.savechat` | Saves a number of messages to a text file and sends it to you. **Bot Owner Only** | `.chatsave 150`
|
||||||
|
|
||||||
|
### Utility
|
||||||
|
Command and aliases | Description | Usage
|
||||||
|
----------------|--------------|-------
|
||||||
|
`.remind` | Sends a message to you or a channel after certain amount of time. First argument is me/here/'channelname'. Second argument is time in a descending order (mo>w>d>h>m) example: 1w5d3h10m. Third argument is a (multiword)message. | `.remind me 1d5h Do something` or `.remind #general Start now!`
|
||||||
|
`.remindmsg` | Sets message for when the remind is triggered. Available placeholders are %user% - user who ran the command, %message% - Message specified in the remind, %target% - target channel of the remind. **Bot Owner Only!**
|
||||||
|
`.serverinfo`, `.sinfo` | Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. | .sinfo Some Server
|
||||||
|
`.channelinfo`, `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | .cinfo #some-channel
|
||||||
|
`.userinfo`, `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | .uinfo @SomeUser
|
||||||
|
`.whoplays` | Shows a list of users who are playing the specified game.
|
||||||
|
`.inrole` | Lists every person from the provided role or roles (separated by a ',') on this server.
|
||||||
|
`.checkmyperms` | Checks your userspecific permissions on this channel.
|
||||||
|
`.stats` | Shows some basic stats for Nadeko.
|
||||||
|
`.dysyd` | Shows some basic stats for Nadeko.
|
||||||
|
`.userid`, `.uid` | Shows user ID.
|
||||||
|
`.channelid`, `.cid` | Shows current channel ID.
|
||||||
|
`.serverid`, `.sid` | Shows current server ID.
|
||||||
|
`.roles` | List all roles on this server or a single user if specified.
|
||||||
|
|
||||||
### Permissions
|
### Permissions
|
||||||
Command and aliases | Description | Usage
|
Command and aliases | Description | Usage
|
||||||
@ -145,8 +152,6 @@ Command and aliases | Description | Usage
|
|||||||
`..` | Adds a new quote with the specified name (single word) and message (no limit). | .. abc My message
|
`..` | Adds a new quote with the specified name (single word) and message (no limit). | .. abc My message
|
||||||
`...` | Shows a random quote with a specified name. | .. abc
|
`...` | Shows a random quote with a specified name. | .. abc
|
||||||
`..qdel`, `..quotedelete` | Deletes all quotes with the specified keyword. You have to either be bot owner or the creator of the quote to delete it. | `..qdel abc`
|
`..qdel`, `..quotedelete` | Deletes all quotes with the specified keyword. You have to either be bot owner or the creator of the quote to delete it. | `..qdel abc`
|
||||||
`@BotName copyme`, `@BotName cm` | Nadeko starts copying everything you say. Disable with cs
|
|
||||||
`@BotName cs`, `@BotName copystop` | Nadeko stops copying you
|
|
||||||
`@BotName rip` | Shows a grave image of someone with a start year | @NadekoBot rip @Someone 2000
|
`@BotName rip` | Shows a grave image of someone with a start year | @NadekoBot rip @Someone 2000
|
||||||
`@BotName uptime` | Shows how long Nadeko has been running for.
|
`@BotName uptime` | Shows how long Nadeko has been running for.
|
||||||
`@BotName die` | Works only for the owner. Shuts the bot down.
|
`@BotName die` | Works only for the owner. Shuts the bot down.
|
||||||
@ -156,7 +161,6 @@ Command and aliases | Description | Usage
|
|||||||
`@BotName slm` | Shows the message where you were last mentioned in this channel (checks last 10k messages)
|
`@BotName slm` | Shows the message where you were last mentioned in this channel (checks last 10k messages)
|
||||||
`@BotName dump` | Dumps all of the invites it can to dump.txt.** Owner Only.**
|
`@BotName dump` | Dumps all of the invites it can to dump.txt.** Owner Only.**
|
||||||
`@BotName ab` | Try to get 'abalabahaha'
|
`@BotName ab` | Try to get 'abalabahaha'
|
||||||
`@BotName av`, `@BotName avatar` | Shows a mentioned person's avatar. | ~av @X
|
|
||||||
|
|
||||||
### Gambling
|
### Gambling
|
||||||
Command and aliases | Description | Usage
|
Command and aliases | Description | Usage
|
||||||
@ -186,6 +190,7 @@ Command and aliases | Description | Usage
|
|||||||
`>pollend` | Stops active poll on this server and prints the results in this channel.
|
`>pollend` | Stops active poll on this server and prints the results in this channel.
|
||||||
`>pick` | Picks a flower planted in this channel.
|
`>pick` | Picks a flower planted in this channel.
|
||||||
`>plant` | Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost)
|
`>plant` | Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost)
|
||||||
|
`>gencurrency`, `>gc` | Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a NadekoFlower. Requires Manage Messages permission. | `>gc`
|
||||||
`>leet` | Converts a text to leetspeak with 6 (1-6) severity levels | >leet 3 Hello
|
`>leet` | Converts a text to leetspeak with 6 (1-6) severity levels | >leet 3 Hello
|
||||||
`>choose` | Chooses a thing from a list of things | >choose Get up;Sleep;Sleep more
|
`>choose` | Chooses a thing from a list of things | >choose Get up;Sleep;Sleep more
|
||||||
`>8ball` | Ask the 8ball a yes/no question.
|
`>8ball` | Ask the 8ball a yes/no question.
|
||||||
@ -195,34 +200,37 @@ Command and aliases | Description | Usage
|
|||||||
### Music
|
### Music
|
||||||
Command and aliases | Description | Usage
|
Command and aliases | Description | Usage
|
||||||
----------------|--------------|-------
|
----------------|--------------|-------
|
||||||
`!m next`, `!m n`, `!m skip` | Goes to the next song in the queue. You have to be in the same voice channel as the bot. | `!m n`
|
`! next`, `! n`, `! skip` | Goes to the next song in the queue. You have to be in the same voice channel as the bot. | `!m n`
|
||||||
`!m stop`, `!m s` | Stops the music and clears the playlist. Stays in the channel. | `!m s`
|
`! stop`, `! s` | Stops the music and clears the playlist. Stays in the channel. | `!m s`
|
||||||
`!m destroy`, `!m d` | Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour) | `!m d`
|
`! destroy`, `! d` | Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour) | `!m d`
|
||||||
`!m pause`, `!m p` | Pauses or Unpauses the song. | `!m p`
|
`! pause`, `! p` | Pauses or Unpauses the song. | `!m p`
|
||||||
`!m queue`, `!m q`, `!m yq` | Queue a song using keywords or a link. Bot will join your voice channel.**You must be in a voice channel**. | `!m q Dream Of Venice`
|
`! queue`, `! q`, `! yq` | Queue a song using keywords or a link. Bot will join your voice channel.**You must be in a voice channel**. | `!m q Dream Of Venice`
|
||||||
`!m listqueue`, `!m lq` | Lists up to 15 currently queued songs. | `!m lq`
|
`! listqueue`, `! lq` | Lists 15 currently queued songs per page. Default page is 1. | `!m lq` or `!m lq 2`
|
||||||
`!m nowplaying`, `!m np` | Shows the song currently playing. | `!m np`
|
`! nowplaying`, `! np` | Shows the song currently playing. | `!m np`
|
||||||
`!m volume`, `!m vol` | Sets the music volume 0-100% | `!m vol 50`
|
`! volume`, `! vol` | Sets the music volume 0-100% | `!m vol 50`
|
||||||
`!m defvol`, `!m dv` | Sets the default music volume when music playback is started (0-100). Does not persist through restarts. | `!m dv 80`
|
`! defvol`, `! dv` | Sets the default music volume when music playback is started (0-100). Does not persist through restarts. | `!m dv 80`
|
||||||
`!m mute`, `!m min` | Sets the music volume to 0% | `!m min`
|
`! mute`, `! min` | Sets the music volume to 0% | `!m min`
|
||||||
`!m max` | Sets the music volume to 100% (real max is actually 150%). | `!m max`
|
`! max` | Sets the music volume to 100% (real max is actually 150%). | `!m max`
|
||||||
`!m half` | Sets the music volume to 50%. | `!m half`
|
`! half` | Sets the music volume to 50%. | `!m half`
|
||||||
`!m shuffle`, `!m sh` | Shuffles the current playlist. | `!m sh`
|
`! shuffle`, `! sh` | Shuffles the current playlist. | `!m sh`
|
||||||
`!m playlist`, `!m pl` | Queues up to 50 songs from a youtube playlist specified by a link, or keywords. | `!m pl playlist link or name`
|
`! playlist`, `! pl` | Queues up to 50 songs from a youtube playlist specified by a link, or keywords. | `!m pl playlist link or name`
|
||||||
`!m localplaylst`, `!m lopl` | Queues all songs from a directory. **Bot Owner Only!** | `!m lopl C:/music/classical`
|
`! soundcloudpl`, `! scpl` | Queue a soundcloud playlist using a link. | `!m scpl https://soundcloud.com/saratology/sets/symphony`
|
||||||
`!m radio`, `!m ra` | Queues a radio stream from a link. It can be a direct mp3 radio stream, .m3u, .pls .asx or .xspf | `!m ra radio link here`
|
`! localplaylst`, `! lopl` | Queues all songs from a directory. **Bot Owner Only!** | `!m lopl C:/music/classical`
|
||||||
`!m local`, `!m lo` | Queues a local file by specifying a full path. **Bot Owner Only!** | `!m lo C:/music/mysong.mp3`
|
`! radio`, `! ra` | Queues a radio stream from a link. It can be a direct mp3 radio stream, .m3u, .pls .asx or .xspf | `!m ra radio link here`
|
||||||
`!m move`, `!m mv` | Moves the bot to your voice channel. (works only if music is already playing) | `!m mv`
|
`! local`, `! lo` | Queues a local file by specifying a full path. **Bot Owner Only!** | `!m lo C:/music/mysong.mp3`
|
||||||
`!m remove`, `!m rm` | Remove a song by its # in the queue, or 'all' to remove whole queue. | `!m rm 5`
|
`! move`, `! mv` | Moves the bot to your voice channel. (works only if music is already playing) | `!m mv`
|
||||||
`!m movesong`, `!m ms` | Moves a song from one position to another. | `!m ms` 5>3
|
`! remove`, `! rm` | Remove a song by its # in the queue, or 'all' to remove whole queue. | `!m rm 5`
|
||||||
`!m cleanup` | Cleans up hanging voice connections. **Bot Owner Only!** | `!m cleanup`
|
`! movesong`, `! ms` | Moves a song from one position to another. | `! ms` 5>3
|
||||||
`!m reptcursong`, `!m rcs` | Toggles repeat of current song. | `!m rcs`
|
`! cleanup` | Cleans up hanging voice connections. **Bot Owner Only!** | `!m cleanup`
|
||||||
`!m rpeatplaylst`, `!m rpl` | Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue). | `!m rpl`
|
`! reptcursong`, `! rcs` | Toggles repeat of current song. | `!m rcs`
|
||||||
`!m save` | Saves a playlist under a certain name. Name must be no longer than 20 characters and mustn't contain dashes. | `!m save classical1`
|
`! rpeatplaylst`, `! rpl` | Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue). | `!m rpl`
|
||||||
`!m load` | Loads a playlist under a certain name. | `!m load classical-1`
|
`! save` | Saves a playlist under a certain name. Name must be no longer than 20 characters and mustn't contain dashes. | `!m save classical1`
|
||||||
`!m playlists`, `!m pls` | Lists all playlists. Paginated. 20 per page. Default page is 0. | `!m pls 1`
|
`! load` | Loads a playlist under a certain name. | `!m load classical-1`
|
||||||
`!m goto` | Goes to a specific time in seconds in a song.
|
`! playlists`, `! pls` | Lists all playlists. Paginated. 20 per page. Default page is 0. | `!m pls 1`
|
||||||
`!m getlink`, `!m gl` | Shows a link to the currently playing song.
|
`! deleteplaylist`, `! delpls` | Deletes a saved playlist. Only if you made it or if you are the bot owner. | `!m delpls animu-5`
|
||||||
|
`! goto` | Goes to a specific time in seconds in a song.
|
||||||
|
`! getlink`, `! gl` | Shows a link to the currently playing song.
|
||||||
|
`! autoplay`, `! ap` | Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty)
|
||||||
|
|
||||||
### Searches
|
### Searches
|
||||||
Command and aliases | Description | Usage
|
Command and aliases | Description | Usage
|
||||||
@ -232,13 +240,22 @@ Command and aliases | Description | Usage
|
|||||||
`~hitbox`, `~hb` | Notifies this channel when a certain user starts streaming. | ~hitbox SomeStreamer
|
`~hitbox`, `~hb` | Notifies this channel when a certain user starts streaming. | ~hitbox SomeStreamer
|
||||||
`~twitch`, `~tw` | Notifies this channel when a certain user starts streaming. | ~twitch SomeStreamer
|
`~twitch`, `~tw` | Notifies this channel when a certain user starts streaming. | ~twitch SomeStreamer
|
||||||
`~beam`, `~bm` | Notifies this channel when a certain user starts streaming. | ~beam SomeStreamer
|
`~beam`, `~bm` | Notifies this channel when a certain user starts streaming. | ~beam SomeStreamer
|
||||||
|
`~checkhitbox`, `~chhb` | Checks if a certain user is streaming on the hitbox platform. | ~chhb SomeStreamer
|
||||||
|
`~checktwitch`, `~chtw` | Checks if a certain user is streaming on the twitch platform. | ~chtw SomeStreamer
|
||||||
|
`~checkbeam`, `~chbm` | Checks if a certain user is streaming on the beam platform. | ~chbm SomeStreamer
|
||||||
`~removestream`, `~rms` | Removes notifications of a certain streamer on this channel. | ~rms SomeGuy
|
`~removestream`, `~rms` | Removes notifications of a certain streamer on this channel. | ~rms SomeGuy
|
||||||
`~liststreams`, `~ls` | Lists all streams you are following on this server. | ~ls
|
`~liststreams`, `~ls` | Lists all streams you are following on this server. | ~ls
|
||||||
`~convert` | Convert quantities from>to. Like `~convert m>km 1000`
|
`~convert` | Convert quantities from>to. Like `~convert m>km 1000`
|
||||||
`~convertlist` | List of the convertable dimensions and currencies.
|
`~convertlist` | List of the convertable dimensions and currencies.
|
||||||
`~wowjoke` | Get one of Kwoth's penultimate WoW jokes.
|
`~wowjoke` | Get one of Kwoth's penultimate WoW jokes.
|
||||||
`~calculate`, `~calc` | Evaluate a mathematical expression. | ~calc 1+1
|
`~calculate`, `~calc` | Evaluate a mathematical expression. | ~calc 1+1
|
||||||
`~wowjoke` | Get one of Kwoth's penultimate WoW jokes.
|
`~osu` | Shows osu stats for a player. | `~osu Name` or `~osu Name taiko`
|
||||||
|
`~osu b` | Shows information about an osu beatmap. | ~osu b https://osu.ppy.sh/s/127712
|
||||||
|
`~osu top5` | Displays a user's top 5 plays. | ~osu top5 Name
|
||||||
|
`~pokemon`, `~poke` | Searches for a pokemon.
|
||||||
|
`~pokemonability`, `~pokab` | Searches for a pokemon ability.
|
||||||
|
`~memelist` | Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/
|
||||||
|
`~memegen` | Generates a meme from memelist with top and bottom text. | `~memegen biw "gets iced coffee" "in the winter"`
|
||||||
`~we` | Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | ~we Moscow RF
|
`~we` | Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | ~we Moscow RF
|
||||||
`~yt` | Searches youtubes and shows the first result
|
`~yt` | Searches youtubes and shows the first result
|
||||||
`~ani`, `~anime`, `~aq` | Queries anilist for an anime and shows the first result.
|
`~ani`, `~anime`, `~aq` | Queries anilist for an anime and shows the first result.
|
||||||
@ -249,7 +266,6 @@ Command and aliases | Description | Usage
|
|||||||
`~ir` | Pulls a random image using a search parameter. | ~ir cute kitten
|
`~ir` | Pulls a random image using a search parameter. | ~ir cute kitten
|
||||||
`~lmgtfy` | Google something for an idiot.
|
`~lmgtfy` | Google something for an idiot.
|
||||||
`~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | ~hs Ysera
|
`~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | ~hs Ysera
|
||||||
`~osu` | Shows osu stats for a player. | ~osu Name
|
|
||||||
`~ud` | Searches Urban Dictionary for a word. | ~ud Pineapple
|
`~ud` | Searches Urban Dictionary for a word. | ~ud Pineapple
|
||||||
`~#` | Searches Tagdef.com for a hashtag. | ~# ff
|
`~#` | Searches Tagdef.com for a hashtag. | ~# ff
|
||||||
`~quote` | Shows a random quote.
|
`~quote` | Shows a random quote.
|
||||||
@ -264,6 +280,7 @@ Command and aliases | Description | Usage
|
|||||||
`~wiki` | Gives you back a wikipedia link
|
`~wiki` | Gives you back a wikipedia link
|
||||||
`~clr` | Shows you what color corresponds to that hex. | `~clr 00ff00`
|
`~clr` | Shows you what color corresponds to that hex. | `~clr 00ff00`
|
||||||
`~videocall` | Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message.
|
`~videocall` | Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message.
|
||||||
|
`~av`, `~avatar` | Shows a mentioned person's avatar. | ~av @X
|
||||||
|
|
||||||
### NSFW
|
### NSFW
|
||||||
Command and aliases | Description | Usage
|
Command and aliases | Description | Usage
|
||||||
|
Loading…
Reference in New Issue
Block a user