mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
All log entries regarding timers now contain a short description of the timer
This commit is contained in:
parent
f1c9ad7a5e
commit
f1494502a7
1
HISTORY
1
HISTORY
@ -3472,3 +3472,4 @@ Video Disk Recorder Revision History
|
|||||||
- Improved falling back to normal recording if the VPS data hasn't been seen for more
|
- Improved falling back to normal recording if the VPS data hasn't been seen for more
|
||||||
than 30 seconds.
|
than 30 seconds.
|
||||||
- Added a missing cMutexLock to cRemote::HasKeys() (thanks to Wolfgang Rohdewald).
|
- Added a missing cMutexLock to cRemote::HasKeys() (thanks to Wolfgang Rohdewald).
|
||||||
|
- All log entries regarding timers now contain a short description of the timer.
|
||||||
|
18
menu.c
18
menu.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: menu.c 1.347 2005/03/20 11:26:00 kls Exp $
|
* $Id: menu.c 1.348 2005/03/20 15:14:51 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
@ -690,7 +690,7 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
|
|||||||
Timers.Add(timer);
|
Timers.Add(timer);
|
||||||
timer->Matches();
|
timer->Matches();
|
||||||
Timers.SetModified();
|
Timers.SetModified();
|
||||||
isyslog("timer %d %s (%s)", timer->Index() + 1, addIfConfirmed ? "added" : "modified", timer->HasFlags(tfActive) ? "active" : "inactive");
|
isyslog("timer %s %s (%s)", *timer->ToDescr(), addIfConfirmed ? "added" : "modified", timer->HasFlags(tfActive) ? "active" : "inactive");
|
||||||
addIfConfirmed = false;
|
addIfConfirmed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -809,9 +809,9 @@ eOSState cMenuTimers::OnOff(void)
|
|||||||
RefreshCurrent();
|
RefreshCurrent();
|
||||||
DisplayCurrent(true);
|
DisplayCurrent(true);
|
||||||
if (timer->FirstDay())
|
if (timer->FirstDay())
|
||||||
isyslog("timer %d first day set to %s", timer->Index() + 1, *timer->PrintFirstDay());
|
isyslog("timer %s first day set to %s", *timer->ToDescr(), *timer->PrintFirstDay());
|
||||||
else
|
else
|
||||||
isyslog("timer %d %sactivated", timer->Index() + 1, timer->HasFlags(tfActive) ? "" : "de");
|
isyslog("timer %s %sactivated", *timer->ToDescr(), timer->HasFlags(tfActive) ? "" : "de");
|
||||||
Timers.SetModified();
|
Timers.SetModified();
|
||||||
}
|
}
|
||||||
return osContinue;
|
return osContinue;
|
||||||
@ -821,7 +821,7 @@ eOSState cMenuTimers::Edit(void)
|
|||||||
{
|
{
|
||||||
if (HasSubMenu() || Count() == 0)
|
if (HasSubMenu() || Count() == 0)
|
||||||
return osContinue;
|
return osContinue;
|
||||||
isyslog("editing timer %d", CurrentTimer()->Index() + 1);
|
isyslog("editing timer %s", *CurrentTimer()->ToDescr());
|
||||||
return AddSubMenu(new cMenuEditTimer(CurrentTimer()));
|
return AddSubMenu(new cMenuEditTimer(CurrentTimer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,12 +846,11 @@ eOSState cMenuTimers::Delete(void)
|
|||||||
else
|
else
|
||||||
return osContinue;
|
return osContinue;
|
||||||
}
|
}
|
||||||
int Index = ti->Index();
|
isyslog("deleting timer %s", *ti->ToDescr());
|
||||||
Timers.Del(ti);
|
Timers.Del(ti);
|
||||||
cOsdMenu::Del(Current());
|
cOsdMenu::Del(Current());
|
||||||
Timers.SetModified();
|
Timers.SetModified();
|
||||||
Display();
|
Display();
|
||||||
isyslog("timer %d deleted", Index + 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return osContinue;
|
return osContinue;
|
||||||
@ -1617,9 +1616,8 @@ eOSState cMenuRecordings::Delete(void)
|
|||||||
timer->Skip();
|
timer->Skip();
|
||||||
cRecordControls::Process(time(NULL));
|
cRecordControls::Process(time(NULL));
|
||||||
if (timer->IsSingleEvent()) {
|
if (timer->IsSingleEvent()) {
|
||||||
int Index = timer->Index();
|
isyslog("deleting timer %s", *timer->ToDescr());
|
||||||
Timers.Del(timer);
|
Timers.Del(timer);
|
||||||
isyslog("timer %d deleted", Index + 1);
|
|
||||||
}
|
}
|
||||||
Timers.SetModified();
|
Timers.SetModified();
|
||||||
}
|
}
|
||||||
@ -3172,7 +3170,7 @@ void cRecordControls::Stop(const char *InstantId)
|
|||||||
cTimer *timer = RecordControls[i]->Timer();
|
cTimer *timer = RecordControls[i]->Timer();
|
||||||
RecordControls[i]->Stop();
|
RecordControls[i]->Stop();
|
||||||
if (timer) {
|
if (timer) {
|
||||||
isyslog("deleting timer %d", timer->Index() + 1);
|
isyslog("deleting timer %s", *timer->ToDescr());
|
||||||
Timers.Del(timer);
|
Timers.Del(timer);
|
||||||
Timers.SetModified();
|
Timers.SetModified();
|
||||||
}
|
}
|
||||||
|
12
svdrp.c
12
svdrp.c
@ -10,7 +10,7 @@
|
|||||||
* and interact with the Video Disk Recorder - or write a full featured
|
* and interact with the Video Disk Recorder - or write a full featured
|
||||||
* graphical interface that sits on top of an SVDRP connection.
|
* graphical interface that sits on top of an SVDRP connection.
|
||||||
*
|
*
|
||||||
* $Id: svdrp.c 1.68 2005/03/19 16:05:33 kls Exp $
|
* $Id: svdrp.c 1.69 2005/03/20 15:04:00 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "svdrp.h"
|
#include "svdrp.h"
|
||||||
@ -529,9 +529,9 @@ void cSVDRP::CmdDELT(const char *Option)
|
|||||||
cTimer *timer = Timers.Get(strtol(Option, NULL, 10) - 1);
|
cTimer *timer = Timers.Get(strtol(Option, NULL, 10) - 1);
|
||||||
if (timer) {
|
if (timer) {
|
||||||
if (!timer->Recording()) {
|
if (!timer->Recording()) {
|
||||||
|
isyslog("deleting timer %s", *timer->ToDescr());
|
||||||
Timers.Del(timer);
|
Timers.Del(timer);
|
||||||
Timers.SetModified();
|
Timers.SetModified();
|
||||||
isyslog("timer %s deleted", Option);
|
|
||||||
Reply(250, "Timer \"%s\" deleted", Option);
|
Reply(250, "Timer \"%s\" deleted", Option);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -919,7 +919,7 @@ void cSVDRP::CmdMODT(const char *Option)
|
|||||||
}
|
}
|
||||||
*timer = t;
|
*timer = t;
|
||||||
Timers.SetModified();
|
Timers.SetModified();
|
||||||
isyslog("timer %d modified (%s)", timer->Index() + 1, timer->HasFlags(tfActive) ? "active" : "inactive");
|
isyslog("timer %s modified (%s)", *timer->ToDescr(), timer->HasFlags(tfActive) ? "active" : "inactive");
|
||||||
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
|
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -977,7 +977,7 @@ void cSVDRP::CmdNEWT(const char *Option)
|
|||||||
if (!t) {
|
if (!t) {
|
||||||
Timers.Add(timer);
|
Timers.Add(timer);
|
||||||
Timers.SetModified();
|
Timers.SetModified();
|
||||||
isyslog("timer %d added", timer->Index() + 1);
|
isyslog("timer %s added", *timer->ToDescr());
|
||||||
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
|
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1051,11 +1051,11 @@ void cSVDRP::CmdUPDT(const char *Option)
|
|||||||
t->Parse(Option);
|
t->Parse(Option);
|
||||||
delete timer;
|
delete timer;
|
||||||
timer = t;
|
timer = t;
|
||||||
isyslog("timer %d updated", timer->Index() + 1);
|
isyslog("timer %s updated", *timer->ToDescr());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Timers.Add(timer);
|
Timers.Add(timer);
|
||||||
isyslog("timer %d added", timer->Index() + 1);
|
isyslog("timer %s added", *timer->ToDescr());
|
||||||
}
|
}
|
||||||
Timers.SetModified();
|
Timers.SetModified();
|
||||||
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
|
Reply(250, "%d %s", timer->Index() + 1, *timer->ToText());
|
||||||
|
25
timers.c
25
timers.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: timers.c 1.29 2005/03/20 14:18:04 kls Exp $
|
* $Id: timers.c 1.30 2005/03/20 14:50:37 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
@ -115,6 +115,13 @@ cString cTimer::ToText(bool UseChannelID)
|
|||||||
return cString(buffer, true);
|
return cString(buffer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cString cTimer::ToDescr(void) const
|
||||||
|
{
|
||||||
|
char *buffer;
|
||||||
|
asprintf(&buffer, "%d (%d %04d-%04d '%s')", Index() + 1, Channel()->Number(), start, stop, file);
|
||||||
|
return cString(buffer, true);
|
||||||
|
}
|
||||||
|
|
||||||
int cTimer::TimeToInt(int t)
|
int cTimer::TimeToInt(int t)
|
||||||
{
|
{
|
||||||
return (t / 100 * 60 + t % 100) * 60;
|
return (t / 100 * 60 + t % 100) * 60;
|
||||||
@ -203,7 +210,7 @@ cString cTimer::PrintDay(time_t Day, int WeekDays)
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
cString cTimer::PrintFirstDay(void)
|
cString cTimer::PrintFirstDay(void) const
|
||||||
{
|
{
|
||||||
if (weekdays) {
|
if (weekdays) {
|
||||||
cString s = PrintDay(day, weekdays);
|
cString s = PrintDay(day, weekdays);
|
||||||
@ -367,7 +374,7 @@ bool cTimer::Matches(time_t t, bool Directly) const
|
|||||||
|
|
||||||
#define FULLMATCH 1000
|
#define FULLMATCH 1000
|
||||||
|
|
||||||
int cTimer::Matches(const cEvent *Event, int *Overlap)
|
int cTimer::Matches(const cEvent *Event, int *Overlap) const
|
||||||
{
|
{
|
||||||
// Overlap is the percentage of the Event's duration that is covered by
|
// Overlap is the percentage of the Event's duration that is covered by
|
||||||
// this timer (based on FULLMATCH for finer granularity than just 100).
|
// this timer (based on FULLMATCH for finer granularity than just 100).
|
||||||
@ -396,7 +403,7 @@ int cTimer::Matches(const cEvent *Event, int *Overlap)
|
|||||||
|
|
||||||
#define EXPIRELATENCY 60 // seconds (just in case there's a short glitch in the VPS signal)
|
#define EXPIRELATENCY 60 // seconds (just in case there's a short glitch in the VPS signal)
|
||||||
|
|
||||||
bool cTimer::Expired(void)
|
bool cTimer::Expired(void) const
|
||||||
{
|
{
|
||||||
return IsSingleEvent() && !Recording() && StopTime() + EXPIRELATENCY <= time(NULL);
|
return IsSingleEvent() && !Recording() && StopTime() + EXPIRELATENCY <= time(NULL);
|
||||||
}
|
}
|
||||||
@ -422,10 +429,10 @@ void cTimer::SetEvent(const cSchedule *Schedule, const cEvent *Event)
|
|||||||
char vpsbuf[64] = "";
|
char vpsbuf[64] = "";
|
||||||
if (Event->Vps())
|
if (Event->Vps())
|
||||||
sprintf(vpsbuf, "(VPS: %s) ", *Event->GetVpsString());
|
sprintf(vpsbuf, "(VPS: %s) ", *Event->GetVpsString());
|
||||||
isyslog("timer %d (%d %04d-%04d '%s') set to event %s %s-%s %s'%s'", Index() + 1, Channel()->Number(), start, stop, file, *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString(), vpsbuf, Event->Title());
|
isyslog("timer %s set to event %s %s-%s %s'%s'", *ToDescr(), *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString(), vpsbuf, Event->Title());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
isyslog("timer %d (%d %04d-%04d '%s') set to no event", Index() + 1, Channel()->Number(), start, stop, file);
|
isyslog("timer %s set to no event", *ToDescr());
|
||||||
schedule = Event ? Schedule : NULL;
|
schedule = Event ? Schedule : NULL;
|
||||||
event = Event;
|
event = Event;
|
||||||
}
|
}
|
||||||
@ -434,7 +441,7 @@ void cTimer::SetEvent(const cSchedule *Schedule, const cEvent *Event)
|
|||||||
void cTimer::SetRecording(bool Recording)
|
void cTimer::SetRecording(bool Recording)
|
||||||
{
|
{
|
||||||
recording = Recording;
|
recording = Recording;
|
||||||
isyslog("timer %d (%d %04d-%04d '%s') %s", Index() + 1, Channel()->Number(), start, stop, file, recording ? "start" : "stop");
|
isyslog("timer %s %s", *ToDescr(), recording ? "start" : "stop");
|
||||||
}
|
}
|
||||||
|
|
||||||
void cTimer::SetPending(bool Pending)
|
void cTimer::SetPending(bool Pending)
|
||||||
@ -445,7 +452,7 @@ void cTimer::SetPending(bool Pending)
|
|||||||
void cTimer::SetInVpsMargin(bool InVpsMargin)
|
void cTimer::SetInVpsMargin(bool InVpsMargin)
|
||||||
{
|
{
|
||||||
if (InVpsMargin && !inVpsMargin)
|
if (InVpsMargin && !inVpsMargin)
|
||||||
isyslog("timer %d (%d %04d-%04d '%s') entered VPS margin", Index() + 1, Channel()->Number(), start, stop, file);
|
isyslog("timer %s entered VPS margin", *ToDescr());
|
||||||
inVpsMargin = InVpsMargin;
|
inVpsMargin = InVpsMargin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -627,7 +634,7 @@ void cTimers::DeleteExpired(void)
|
|||||||
while (ti) {
|
while (ti) {
|
||||||
cTimer *next = Next(ti);
|
cTimer *next = Next(ti);
|
||||||
if (ti->Expired()) {
|
if (ti->Expired()) {
|
||||||
isyslog("deleting timer %d", ti->Index() + 1);
|
isyslog("deleting timer %s", *ti->ToDescr());
|
||||||
Del(ti);
|
Del(ti);
|
||||||
SetModified();
|
SetModified();
|
||||||
}
|
}
|
||||||
|
43
timers.h
43
timers.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: timers.h 1.17 2005/03/20 12:36:25 kls Exp $
|
* $Id: timers.h 1.18 2005/03/20 14:47:45 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TIMERS_H
|
#ifndef __TIMERS_H
|
||||||
@ -30,8 +30,8 @@ private:
|
|||||||
bool recording, pending, inVpsMargin;
|
bool recording, pending, inVpsMargin;
|
||||||
int flags;
|
int flags;
|
||||||
cChannel *channel;
|
cChannel *channel;
|
||||||
mutable time_t day; /// midnight of the day this timer shall hit, or of the first day it shall hit in case of a repeating timer
|
mutable time_t day; ///< midnight of the day this timer shall hit, or of the first day it shall hit in case of a repeating timer
|
||||||
int weekdays; /// bitmask, lowest bits: SSFTWTM (the 'M' is the LSB)
|
int weekdays; ///< bitmask, lowest bits: SSFTWTM (the 'M' is the LSB)
|
||||||
int start;
|
int start;
|
||||||
int stop;
|
int stop;
|
||||||
int priority;
|
int priority;
|
||||||
@ -46,22 +46,23 @@ public:
|
|||||||
virtual ~cTimer();
|
virtual ~cTimer();
|
||||||
cTimer& operator= (const cTimer &Timer);
|
cTimer& operator= (const cTimer &Timer);
|
||||||
virtual int Compare(const cListObject &ListObject) const;
|
virtual int Compare(const cListObject &ListObject) const;
|
||||||
bool Recording(void) { return recording; }
|
bool Recording(void) const { return recording; }
|
||||||
bool Pending(void) { return pending; }
|
bool Pending(void) const { return pending; }
|
||||||
bool InVpsMargin(void) { return inVpsMargin; }
|
bool InVpsMargin(void) const { return inVpsMargin; }
|
||||||
int Flags(void) { return flags; }
|
int Flags(void) const { return flags; }
|
||||||
const cChannel *Channel(void) { return channel; }
|
const cChannel *Channel(void) const { return channel; }
|
||||||
time_t Day(void) { return day; }
|
time_t Day(void) const { return day; }
|
||||||
int WeekDays(void) { return weekdays; }
|
int WeekDays(void) const { return weekdays; }
|
||||||
int Start(void) { return start; }
|
int Start(void) const { return start; }
|
||||||
int Stop(void) { return stop; }
|
int Stop(void) const { return stop; }
|
||||||
int Priority(void) { return priority; }
|
int Priority(void) const { return priority; }
|
||||||
int Lifetime(void) { return lifetime; }
|
int Lifetime(void) const { return lifetime; }
|
||||||
const char *File(void) { return file; }
|
const char *File(void) const { return file; }
|
||||||
time_t FirstDay(void) { return weekdays ? day : 0; }
|
time_t FirstDay(void) const { return weekdays ? day : 0; }
|
||||||
const char *Summary(void) { return summary; }
|
const char *Summary(void) const { return summary; }
|
||||||
cString ToText(bool UseChannelID = false);
|
cString ToText(bool UseChannelID = false);
|
||||||
const cEvent *Event(void) { return event; }
|
cString ToDescr(void) const;
|
||||||
|
const cEvent *Event(void) const { return event; }
|
||||||
bool Parse(const char *s);
|
bool Parse(const char *s);
|
||||||
bool Save(FILE *f);
|
bool Save(FILE *f);
|
||||||
bool IsSingleEvent(void) const;
|
bool IsSingleEvent(void) const;
|
||||||
@ -72,8 +73,8 @@ public:
|
|||||||
static time_t SetTime(time_t t, int SecondsFromMidnight);
|
static time_t SetTime(time_t t, int SecondsFromMidnight);
|
||||||
char *SetFile(const char *File);
|
char *SetFile(const char *File);
|
||||||
bool Matches(time_t t = 0, bool Directly = false) const;
|
bool Matches(time_t t = 0, bool Directly = false) const;
|
||||||
int Matches(const cEvent *Event, int *Overlap = NULL);
|
int Matches(const cEvent *Event, int *Overlap = NULL) const;
|
||||||
bool Expired(void);
|
bool Expired(void) const;
|
||||||
time_t StartTime(void) const;
|
time_t StartTime(void) const;
|
||||||
time_t StopTime(void) const;
|
time_t StopTime(void) const;
|
||||||
void SetEvent(const cSchedule *Schedule, const cEvent *Event);
|
void SetEvent(const cSchedule *Schedule, const cEvent *Event);
|
||||||
@ -86,7 +87,7 @@ public:
|
|||||||
bool HasFlags(int Flags) const;
|
bool HasFlags(int Flags) const;
|
||||||
void Skip(void);
|
void Skip(void);
|
||||||
void OnOff(void);
|
void OnOff(void);
|
||||||
cString PrintFirstDay(void);
|
cString PrintFirstDay(void) const;
|
||||||
static int TimeToInt(int t);
|
static int TimeToInt(int t);
|
||||||
static bool ParseDay(const char *s, time_t &Day, int &WeekDays);
|
static bool ParseDay(const char *s, time_t &Day, int &WeekDays);
|
||||||
static cString PrintDay(time_t Day, int WeekDays);
|
static cString PrintDay(time_t Day, int WeekDays);
|
||||||
|
4
tools.c
4
tools.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: tools.c 1.90 2005/02/19 13:43:03 kls Exp $
|
* $Id: tools.c 1.91 2005/03/20 14:44:33 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
@ -896,7 +896,7 @@ void cListObject::Unlink(void)
|
|||||||
next = prev = NULL;
|
next = prev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cListObject::Index(void)
|
int cListObject::Index(void) const
|
||||||
{
|
{
|
||||||
cListObject *p = prev;
|
cListObject *p = prev;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
4
tools.h
4
tools.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: tools.h 1.67 2005/02/12 10:17:14 kls Exp $
|
* $Id: tools.h 1.68 2005/03/20 14:44:24 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __TOOLS_H
|
#ifndef __TOOLS_H
|
||||||
@ -202,7 +202,7 @@ public:
|
|||||||
void Append(cListObject *Object);
|
void Append(cListObject *Object);
|
||||||
void Insert(cListObject *Object);
|
void Insert(cListObject *Object);
|
||||||
void Unlink(void);
|
void Unlink(void);
|
||||||
int Index(void);
|
int Index(void) const;
|
||||||
cListObject *Prev(void) const { return prev; }
|
cListObject *Prev(void) const { return prev; }
|
||||||
cListObject *Next(void) const { return next; }
|
cListObject *Next(void) const { return next; }
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user